我想为一个符合泛型协议的泛型类创建一个包装类,但是由于某些原因,我无法使它正常工作。
其背后的思想是使用包装器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协议。顺便说一句,我不明白为什么会这样。未满足的需求是requestSerializerrequestResponse属性以及所需的类型别名。一般来说,您可以重写如下:

public class AnyNetworkRequest: NetworkRequest {

    var requestSerializer: RequestSerializationType {
       return request.requestSerializer
    }

    var requestResponse: RequestResponseType? {
       return request.requestResponse
    }

    private let request : _NetworkRequest<RequestSerializationType, RequestResponseType>

   // ...
}

但我们需要
2)需要为关联类型指定内容的位置。不能在泛型声明中使用RequestSerializationTypeRequestResponseType,因为它们不是具体类型。
所以您不能以这种方式执行类型擦除。
我不知道为什么除了键入更少的字母之外,还需要去掉泛型,但我可以提供的是使用类型别名,例如:
typealias DataNetworkRequest = _NetworkRequest<ConcreteHTTPRequestSerializer, ConcreteDataNetworkResponse>

typealias JSONDataNetworkRequest = _NetworkRequest<ConcreteJSONRequestSerializer, ConcreteJSONDataNetworkResponse>

这样你就可以避开多余的继承,并且有更清晰的表示类型,以防这是你的目标。
AnyNetworkRequest在这种情况下根本不需要。

10-07 12:40