我仍然无法理解Swift中泛型的一些细微之处。我定义了以下类型:
protocol SomeProtocol {
func setValue(value: Int)
}
class ProtocolLabel : UILabel, SomeProtocol {
func setValue(value: Int) {
}
}
class ProtocolImageView : UIImageView, SomeProtocol {
func setValue(value: Int) {
}
}
viewForValue(2) 现在我定义了以下功能。我希望 T是一个符合协议SomeProtocol 的UIView。
func viewForValue<T where T: SomeProtocol, T: UIView>(param: Int) -> UIView {
var someView: T
if param > 0 {
someView = ProtocolLabel() as T
} else {
someView = ProtocolImageView() as T
}
someView.setValue(2)
someView.frame = CGRectZero
return someView
}
但是,当我执行代码时,我收到以下编译错误:
viewForValue(2) // <-- Type 'UIView' does not conform to protocol 'SomeProtocol'
似乎在where子句中我不能指定一个不实现协议的类。那是为什么?
提前致谢。
答案 0 :(得分:4)
viewForValue
应该返回一个继承自UIView
并实现SomeProtocol
的类。
您已经定义了两个没有直接关系的类 - 它们只是继承自UIView
并实现SomeProtocol
。
当函数必须确定返回类型时,两个类继承的直接具体类型是UIView
,这就是viewForValue
返回的内容。
为了解决问题,您必须通过创建继承自UIView
并实施SomeProtocol
的第3类来创建2个类之间的直接和具体关系:
protocol SomeProtocol {
func setValue(value: Int)
}
class SomeClass: UIView, SomeProtocol {
func setValue(value: Int) {
}
}
class SomeSubclass : SomeClass {
}
class SomeOtherSubclass : SomeClass {
}
func viewForValue<T where T: SomeProtocol, T: SomeClass>(param: Int) -> T {
var someView: T
if param > 0 {
someView = SomeSubclass() as T
} else {
someView = SomeOtherSubclass() as T
}
someView.setValue(2)
someView.frame = CGRectZero
return someView
}
viewForValue(2)
附录:阅读下面的OP评论,目的是动态实例化从UIView
继承的现有UIKit类。所以提出的解决方案并不适用。
我认为通过实施UIView
扩展SomeProtocol
应该工作:
protocol SomeProtocol {
func setValue(value: Int)
}
extension UIView : SomeProtocol {
func setValue(value: Int) {
}
}
func viewForValue<T where T: SomeProtocol, T: UIView>(param: Int) -> UIView {
var someView: T
if param > 0 {
someView = UILabel() as T
} else {
someView = UIImageView() as T
}
someView.setValue(2)
someView.frame = CGRectZero
return someView
}
但它看起来像编译器错误。操场上的此代码显示一条消息,指出:
与游乐场服务的沟通意外中断。 游乐场服务&#34; com.apple.dt.Xcode.Playground&#34;可能已生成崩溃日志。
而在iOS应用程序中,编译由于分段错误而失败11。