我想为符合通用协议的通用类创建Wrapper类,但是由于某些原因,我无法使其正常工作。
背后的想法是将包装 AnyNetworkRequest 用作应用程序中的Erased-Type,因此无需像 _NetworkRequest 中那样定义泛型类型。
我看不到 AnyNetworkRequest 上缺少/错误的内容。如果有什么可以指出我的缺失或错误之处,我将不胜感激。
// 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
}
}
答案 0 :(得分:1)
错误很容易解释。
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
。
答案 1 :(得分:1)
这实际上不是类型擦除器的工作方式-类型擦除器的作用是允许异构世界中的同类接口,在异构世界中,许多类型可以符合感兴趣的协议。
以AnySequence
为例,它的界面与此类似:
struct AnySequence<Element>: Sequence {
init<S>(_ sequence: S) where S == Sequence, S.Element == Element
}
AnySequence
删除原始序列类型,而不是Element
类型。对于您而言,您无法摆脱两种关联的类型,类型擦除器只能隐藏符合NetworkRequest
的实际类。 AnyRequest
仍需要有关这两种类型的信息。