我想在协议中使用通用闭包。例如:
protocol Fetcher {
func fetchWithSuccess<T>(success doSuccess : (T) -> (), failure doFailure : ((NSError?) -> ()))
}
我认为实现这样的协议会起到这样的作用:
class SimpleFetcher<T> : Fetcher {
let thing : T
init(thing : T) {
self.thing = thing
}
func fetchWithSuccess<T>(success doSuccess : (T) -> (), failure doFailure : ((NSError?) -> ())) {
doSuccess(self.thing) // Fails
}
}
但是,上述代码在'T' is not convertible with 'T'
中失败,错误为doSuccess(self.thing)
。我错过了什么?
值得一提的是,使用课程时没有问题:
class Fetcher<T> {
func fetchWithSuccess(success doSuccess : (T) -> (), failure doFailure : ((NSError?) -> ())) {}
}
class SimpleFetcher<T> : Fetcher<T> {
let thing : T
init(thing : T) {
self.thing = thing
}
override func fetchWithSuccess(success doSuccess : (T) -> (), failure doFailure : ((NSError?) -> ())) {
doSuccess(self.thing)
}
}
答案 0 :(得分:3)
您需要进行两项更改 - 一项在您的协议中,另一项在您的课程中。
在协议中,为关联类型定义typealias
,并让您的方法使用该别名作为类型。泛型类中的方法本身不需要是通用的 - 方法使用类本身的泛型类型。
protocol Fetcher {
typealias Element
func fetchWithSuccess(success doSuccess : (Element) -> (), failure doFailure : ((NSError?) -> ()))
}
然后在您的班级中,声明typealias
为T
,并从方法中删除通用语法:
class SimpleFetcher<T> : Fetcher {
typealias Element = T
let thing : T
init(thing : T) {
self.thing = thing
}
func fetchWithSuccess(success doSuccess : (T) -> (), failure doFailure : ((NSError?) -> ())) {
doSuccess(self.thing) // Fails
}
}
测试:
let s = SimpleFetcher(thing: "Hello")
s.fetchWithSuccess(success: { str in println(str) }, failure: { error in println(error) })
// "Hello"
答案 1 :(得分:2)
有两件事需要解决:
不要使该方法具有通用性,因为该类已经在使用泛型
该类已经定义了T
泛型类型 - 如果在方法中使用<T>
,T
类型与类级别定义的类型没有关系 - 这就解释了为什么你有一个奇怪的错误消息T is not convertible to T
。要验证这一点,只需将函数中的通用名称从T
更改为其他名称。
所以你的功能应该是这样的:
func fetchWithSuccess(success doSuccess : (T) -> (), failure doFailure : ((NSError?) -> ())) {
doSuccess(self.thing) // Fails
}
在协议中定义类型别名
您还必须在协议中定义类型别名,这在概念上类似于类和结构的泛型(阅读Type Alias Declaration和Protocol Associated Type Declaration)
protocol Fetcher {
typealias V
func fetchWithSuccess(success doSuccess : (V) -> (), failure doFailure : ((NSError?) -> ()))
}