我想为一个符合泛型协议的泛型类创建一个包装类,但是由于某些原因,我无法使它正常工作。
其背后的思想是使用包装器AnyNetworkRequest作为应用程序的擦除类型,这样就不需要像在NetworkRequest中那样定义泛型类型。
我看不到任何网络请求中缺少/错误的内容。如果有人能指出我的缺失或错误,我将不胜感激。
// Protocol with associatedtypes
public protocol NetworkRequest {
associatedtype RequestSerializationType: RequestSerializationProtocol
associatedtype RequestResponseType: NetworkResponseProtocol
var requestSerializer: RequestSerializationType { get }
var requestResponse: RequestResponseType? { get }
}
// Generic Request
public class _NetworkRequest<RequestSerializationType: RequestSerializationProtocol, RequestResponseType: NetworkResponseProtocol>: NetworkRequest {
fileprivate init() {}
public lazy var requestSerializer: RequestSerializationType = { RequestSerializationType.init() }()
public var requestResponse: RequestResponseType?
}
// Concrete Request
public class DataNetworkRequest: _NetworkRequest<ConcreteHTTPRequestSerializer, ConcreteDataNetworkResponse> {}
// Concrete Request
public class JSONDataNetworkRequest: _NetworkRequest<ConcreteJSONRequestSerializer, ConcreteJSONDataNetworkResponse> {}
// Type Erased Wrapper
// Cannot make this wrapper work
// Error 1: Type 'AnyNetworkRequest' does not conform to protocol 'NetworkRequest'
// Error 2: Reference to invalid associated type 'RequestSerializationType' of type 'AnyNetworkRequest'
public class AnyNetworkRequest : NetworkRequest { //E1
private let request : _NetworkRequest<RequestSerializationType, RequestResponseType> //E2
init<T: NetworkRequest>(_ networkRequest: T) where T.RequestSerializationType == RequestSerializationType, T.RequestResponseType == RequestResponseType {
request = networkRequest
}
}
编辑:第一次修改
// Protocol with associatedtypes
public protocol NetworkRequest {
associatedtype RequestSerializationType: RequestSerializationProtocol
associatedtype RequestResponseType: NetworkResponseProtocol
var requestSerializer: RequestSerializationType { get }
var requestResponse: RequestResponseType? { get }
}
// Generic Request
public class _NetworkRequest<RST: RequestSerializationProtocol, RRT: NetworkResponseProtocol>: NetworkRequest {
public typealias RequestSerializationType = RST
public typealias RequestResponseType = RRT
fileprivate init() {}
public lazy var requestSerializer: RequestSerializationType = { RequestSerializationType.init() }()
public var requestResponse: RequestResponseType?
}
// Concrete Request
public class DataNetworkRequest: _NetworkRequest<ConcreteHTTPRequestSerializer, ConcreteDataNetworkResponse> {}
// Concrete Request
public class JSONDataNetworkRequest: _NetworkRequest<ConcreteJSONRequestSerializer, ConcreteJSONDataNetworkResponse> {}
// Type Erased Wrapper
// Cannot make this wrapper work
// Error 1: Type 'AnyNetworkRequest' does not conform to protocol 'NetworkRequest'
// Error 2: Reference to invalid associated type 'RequestSerializationType' of type 'AnyNetworkRequest'
public class AnyNetworkRequest : NetworkRequest { //E1
/* // E1 forces me to include typealiases
public typealias RequestSerializationType = <#type#>
public typealias RequestResponseType = <#type#>
*/
private let request : _NetworkRequest<RequestSerializationType, RequestResponseType>
var requestSerializer: RequestSerializationType { //E2
return request.requestSerializer
}
var requestResponse: RequestResponseType? {
return request.requestResponse
}
init<T: NetworkRequest>(_ networkRequest: T) where T.RST == RequestSerializationType, T.RRT == RequestResponseType {
request = networkRequest
}
}
最佳答案
错误很容易解释。
1)您的AnyNetworkRequest
类确实不符合NetworkRequest
协议。顺便说一句,我不明白为什么会这样。未满足的需求是requestSerializer
和requestResponse
属性以及所需的类型别名。一般来说,您可以重写如下:
public class AnyNetworkRequest: NetworkRequest {
var requestSerializer: RequestSerializationType {
return request.requestSerializer
}
var requestResponse: RequestResponseType? {
return request.requestResponse
}
private let request : _NetworkRequest<RequestSerializationType, RequestResponseType>
// ...
}
但我们需要
2)需要为关联类型指定内容的位置。不能在泛型声明中使用
RequestSerializationType
和RequestResponseType
,因为它们不是具体类型。所以您不能以这种方式执行类型擦除。
我不知道为什么除了键入更少的字母之外,还需要去掉泛型,但我可以提供的是使用类型别名,例如:
typealias DataNetworkRequest = _NetworkRequest<ConcreteHTTPRequestSerializer, ConcreteDataNetworkResponse>
typealias JSONDataNetworkRequest = _NetworkRequest<ConcreteJSONRequestSerializer, ConcreteJSONDataNetworkResponse>
这样你就可以避开多余的继承,并且有更清晰的表示类型,以防这是你的目标。
AnyNetworkRequest
在这种情况下根本不需要。