我试图在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。
谢谢!
答案 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>()