为什么这个协议只能用作通用约束"?

时间:2014-07-12 01:56:34

标签: generics swift xcode6

我试图在Swift中执行以下操作:

protocol ProtocolWithAlias {
    typealias T
}

protocol AnotherProtocol {
    func someFunc() -> ProtocolWithAlias
}

但我收到错误:Protocol 'ProtocolWithAlias' can only be used as a generic constraint because it has Self or associated type requirements

有可能做这样的事吗?错误消息(或至少是“only be used as a generic constraint”部分)似乎对我没有多大意义。

我正在使用最新的Xcode 6 beta 3。

谢谢!

2 个答案:

答案 0 :(得分:23)

试试这个:

func someFunc<T:ProtocolWithAlias>() -> T

答案 1 :(得分:13)

可以通过反转控件来实现这一点:而不是从 someFunc 返回一个值,我们传递一个消费者,它可以接受任何实现 ProtocolWithAlias 的类型并用它做一些事情

protocol ProtocolWithAlias {
    typealias T
}

protocol ProtocolConsumer {
    func consume<T: ProtocolWithAlias>(value: T)
}

protocol AnotherProtocol {
    func someFunc(consumer: ProtocolConsumer)
}

这个技巧被称为将函数转换为continuation passing style (CPS)。不幸的是,如果没有CPSing,我找不到任何实现方法。我们正在寻找的类型系统特性是存在类型(this线程有一个很好的解释),但我认为Swift不支持它们(还)。

为什么其他答案不正确?这个签名告诉我们:

func someFunc<T:ProtocolWithAlias>() -> T

是这个函数可以为 调用者 选择的实现 ProtocolWithAlias 的任何类型返回类型T的值,但是我们希望它由 被调用者 选择。

甚至不可能写出这个函数的合理实现。让我假装我有一个 someFunc 的实现:我可以创建一个实现 ProtocolWithAlias 的新类,并请求someFunc以某种方式创建这个类的实例:

class Uninhabited: ProtocolWithAlias {
    typealias T = Int
    init(nope: Uninhabited) {}
}

...

let impossible: Uninhabited = someFunc<Uninhabited>()