无法实例化使用另一个泛型作为参数的泛型类型 - 无法为类型调用初始化程序

时间:2015-08-10 17:17:17

标签: swift generics

class Request {

}
class Response<T: Request> {
    let request: T
    required init(request: T) {
        self.request = request
    }
}
class Adapter {        
    static func MakeRequest<T: Request, N: Response<T>>(request: T) -> N {
        let response = N(request: request)
        return response
    }
}
  

错误:无法为类型&#39; N&#39;调用初始化程序。使用类型的参数列表   &#39;(请求:T)&#39;

我想创建一个响应类,将请求存储为泛型类型。当我尝试实例化传递一般请求的响应时,它返回上面的错误。

2 个答案:

答案 0 :(得分:1)

你想要做的事情没有最大意义。

如果您的所有请求和响应对象都是RequestResponse的子类,那么您就不需要泛型。除了RequestResponse的子类之外,您将无法定义可在Adapter中使用的任何内容。只需定义这样的一切:

class Request {
}
class Response {
    let request: Request
    required init(request: Request) {
        self.request = request
    }
}
class Adapter {
    static func MakeRequest(request: Request) -> Response {
        let response = Response(request: request)
        return response
    }
}

但是,我怀疑你真正想要的是将RequestResponse定义为协议。这将允许您使任何类或结构符合RequestResponse协议,从而可以在Adapter中使用。这对于泛型非常有用。

protocol Request {
}
protocol Response {
    var request: Request { get }
    init(request: Request)
}
class Adapter {
    static func MakeRequest<T: Request, N: Response>(request: T) -> N {
        let response = N(request: request)
        return response
    }
}

修改

根据您的评论,我发现您要在Request中使用Response的子类,而不必进行类型转换。当然,仿制药可以使这成为可能,但它对你没用。

想象一下,您按照以下方式定义了RequestResponse类:

class Request {
}
class Response<T: Request> {
    let request: T
    required init(request: T) {
        self.request = request
    }
}

你有一个特殊的Request子类定义为MyRequest,它包含一个额外的属性:

class MyRequest: Request {
    let numberOfRetries: Int = 3
}

您创建的回复包含MyRequest

let myRequest = MyRequest()
let aResponse = Response(request: myRequest)

这一切都有效。但你能用它做什么呢?在游乐场,您可以查看numberOfRetries并查看它是否有效:

aResponse.request.numberOfRetries     // 3

但你不能在真正的应用程序中编写任何代码来利用这一点。以Adapter为例,任何Adapter实例都无法在没有专业的情况下检查numberOfRetries,因为通用Adapter接受通用Response接受通用Request将无法假定请求是MyRequest实例,因此无法假定numberOfRetries存在。

如果您希望Adapter能够通过类型转换或检查来利用RequestResponse子类的功能,则需要一个专门的Adapter子类对它处理的RequestResponse的限制。如果你正在创建一个Adapter子类,我会说在你的情况下泛型的用处非常有限。

换句话说,Adapter实例(或处理Response个对象的任何其他代码)将无法利用Response子类的特殊功能而无需进行类型转换,具体而言因为您使用泛型意味着Adapter无法假设它将使用哪种Response

答案 1 :(得分:0)

鉴于您的问题和对@ user2194039的评论,它可能是直接实例化它的最佳方式,因为您需要提供类型信息:

// if the function would work in your example you have to call it like so
let response: URLResponse<String> = Adapter.MakeRequest("Hello")

// this would be the easiest way
let response = URLResponse("Hello")

如果您的示例更复杂,请提供更多信息。