协议中的通用闭包

时间:2014-09-18 14:22:35

标签: generics swift

我想在协议中使用通用闭包。例如:

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)
    }
}

2 个答案:

答案 0 :(得分:3)

您需要进行两项更改 - 一项在您的协议中,另一项在您的课程中。

在协议中,为关联类型定义typealias,并让您的方法使用该别名作为类型。泛型类中的方法本身不需要是通用的 - 方法使用类本身的泛型类型。

protocol Fetcher {
    typealias Element

    func fetchWithSuccess(success doSuccess : (Element) -> (), failure doFailure : ((NSError?) -> ()))
}

然后在您的班级中,声明typealiasT,并从方法中删除通用语法:

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 DeclarationProtocol Associated Type Declaration

protocol Fetcher {
    typealias V
    func fetchWithSuccess(success doSuccess : (V) -> (), failure doFailure : ((NSError?) -> ()))
}