这是我在StackOverflow上的第一个问题,所以请放心。
我一直在努力让Swift调用适当的泛型重载。
假设我有以下协议-
protocol MyProtocol { }
我有以下通用方法-
func foo<T>() -> T
func foo<T: MyProtocol>() -> T
可以预期,用符合MyProtocol
的返回类型T
调用foo()
将调用适当的重载。
let bar: MyProtocol = foo()
上面的代码实际上在运行时调用了以下函数,IDE中的Cmd+Click也会导航到错误的重载。
func foo<T>() -> T
由于某些原因,我无法在Xcode 7.1.1中正常工作。
我是在这里错过了一些完全基本的东西,还是这是斯威夫特的另一个怪癖?
编辑
根据matt的请求添加一个该行为的示例。
protocol MyProtocol { }
class MyProtoClass : MyProtocol { }
class Bar {
func foo<T>(value: T) {
print("T is Generic")
}
func foo(value: MyProtocol) {
print("T conforms to MyProtocol")
}
}
class MyClass<T> {
var value: T
init(value: T) { self.value = value }
var b = Bar()
func print() {
b.foo(value)
}
}
MyClass<MyProtocol>(value: MyProtoClass()).print()
MyClass<String>(value: "").print()
将上面的代码复制并粘贴到Swift命令行应用程序中并执行会产生以下输出。
T is Generic
T is Generic
我认为这里的问题是泛型中的协议(通常是Swift中的协议)不能按照你想要的方式工作。它们不是一流的类型。我知道这很模糊。。。但从这个角度来看;如果删除foo
的func foo<T>(value: T)
版本,则代码甚至无法编译。换言之,斯威夫特没有选择foo
,也没有选错;就是说CCD_ 7不调用CCD_。
我有一种模糊的感觉,这与我在这里的问题有关:
协议没有';不符合自己吗?
好的,我将在这里回答我自己的问题。
经过一些调查,Swift似乎希望您在泛型参数上实现一个具有类型约束的扩展。
extension MyClass where T : MyProtocol {
func print() {
b.foo(value)
}
}
我知道这并不能真正解决问题,但对于我来说,在现实世界的用例中,这已经足够了。
上面的样本最终会看起来像下面这样。
protocol MyProtocol { }
class MyProtoClass : MyProtocol { }
class Bar {
func foo<T>(value: T) {
print("T is Generic")
}
func foo(value: MyProtocol) {
print("T conforms to MyProtocol")
}
}
class MyClass<T> {
var value: T
init(value: T) { self.value = value }
var b = Bar()
func print() {
b.foo(value)
}
}
extension MyClass where T : MyProtocol {
func print() {
b.foo(value)
}
}
MyClass<MyProtoClass>(value: MyProtoClass()).print()
MyClass<String>(value: "").print()