【发布时间】:2015-01-31 11:34:41
【问题描述】:
我有一个这样定义的 Swift 协议:
protocol MyProtocol {
func genericMethod<T:MyProtocol>(param:T) -> ()
}
我可以像这样在基类中实现泛型方法:
class MyBaseClass : MyProtocol {
func genericMethod<T where T:MyProtocol>(param:T) -> () {
println("Performing generic method for type \(T.self)")
}
}
class MySubClass : MyBaseClass {
...
}
到目前为止,一切都很好。我可以实现这个方法,它编译和运行都很好。
现在,我想做一些类似的事情,但在我的基类中,我想通过要求它符合诸如Comparable 之类的协议来进一步限制泛型方法的类型。我试试这个:
class MyBaseClass : MyProtocol {
func genericMethod<T where T:MyProtocol, T:Comparable>(param:T) -> () {
println("Performing generic method for type \(T.self)")
}
}
一旦我在类型 T 上添加了这个附加约束,类 MyClass 将无法编译,因为它不再符合协议。
似乎在泛型类型上添加额外的约束不应该导致它停止符合协议。我错过了什么?在我看来,协议是说genericMethod 必须传递一个符合MyProtocol 类型的参数。当我在MyBaseClass 中实现它时——只是MyProtocol 的一种可能实现——我应该能够进一步限制该实现,方法是说参数 myst 符合Comparable 除了 MyProtocol
有没有办法像我在这里尝试的那样在基本实现中细化泛型类型?
【问题讨论】:
-
我不明白你为什么感到惊讶。也许我遗漏了一些明显的东西,但在我看来,协议说:“采用我的人必须实现
genericMethod,参数是他自己的类型。但T:MyBaseClass, T:Comparable不是 MyBaseClass 自己的类型,因为 MyBaseClass 不采用 Comparable。因此,正如编译器所说,您违反了协议规定的合同。 -
在协议中使用
Self引用只是演示问题的一种方式。如果我使用一个协议然后另一个协议,我会遇到同样的问题。我将更新问题以更清楚地说明为什么我对这种行为感到惊讶 -
好的,感谢修改。好吧,编译器为什么不喜欢它的问题的答案是这些不匹配。协议要求
func genericMethod<T:MyProtocol>(param:T) -> ()与func genericMethod<T where T:MyProtocol, T:Comparable>(param:T) -> ()不同。您在一种心理上的正当脚注中说“一个是另一个的更受限制的版本”,但这对编译器无关紧要;关键是一个不是另一个。 -
要查看此内容,请尝试更简单的变体:
func genericMethod<T> (param:T) -> ()和func genericMethod<T where T:Comparable>(param:T) -> ()。他们也不匹配,我认为原因更清楚。换句话说,您似乎认为一个泛型是另一个泛型的一种“子类”或“子集”。但这不是这些通用签名的工作方式。要么匹配,要么不匹配。 -
我建议你复习一下里氏替换原则en.wikipedia.org/wiki/Liskov_substitution_principle