swift - 无法实例化使用另一个泛型作为参数的泛型类型 - 无法为类型调用初始值设定项

标签 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
    }
}

Error: Cannot invoke initializer for type 'N' with an argument list of type '(request: T)'

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

最佳答案

您尝试做的事情没有多大意义。

如果您所有的请求和响应对象都将成为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 定义为协议(protocol)。这将允许您使任何类或结构符合 RequestResponse 协议(protocol),因此可以在您的 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
    }
}

编辑

根据您的评论,我发现您希望在 Response 中使用 Request 的子类,而无需进行类型转换。当然,泛型可以使这成为可能,但它对您没有用。

想象一下,您定义了 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)

这一切都有效。但是你能用它做什么呢?在 Playground 上,您可以检查 numberOfRetries 并查看它是否正常工作:

aResponse.request.numberOfRetries     // 3

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

如果您希望您的 Adapter 能够利用 RequestResponse 子类的类型转换或检查功能,您需要一个专门的 Adapter 子类,对它处理的 RequestResponse 有限制。如果您要创建一个 Adapter 子类,我会说泛型在您的情况下的用处将受到严重限制。

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

关于swift - 无法实例化使用另一个泛型作为参数的泛型类型 - 无法为类型调用初始值设定项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31925464/

相关文章:

ios - UI TableView 不返回数据

ios - 以编程方式将段落标题添加到 UITextView

java - 可能的 eclipse 错误

c# - 通过多个派生类传递类型参数以在通用静态构造函数中使用

swift - 如何快速获取磁盘上图像的颜色配置文件数据

swift - 在 Swift 中将 GPS 坐标转换为城市名称/地址

ios - Swift 和 UIKit 中的曲线动画 - 从起点/终点开始的抛物线运动

ios - 通用 View Controller 无法与委托(delegate)和扩展一起使用

c# - 使用基类作为 IEnumerable<T> 的泛型

c# - C# 泛型方法中的 "where T : class"是什么?