这是一个很好的旧时尚单继承OO类树的例子:
class Common {
var foo:String = ""
var bar:Int = 0
// common behavior to deal with foo + bar
}
class SubA:Common {
var yak:Double = 0.0
// specialized behavior to deal with yak, foo, and bar
}
class SubB:Common {
var baz:CGFloat = 1.0
// specialized behavior to deal with baz, foo, and bar
}
非常简单。 Swift为我们提供了许多思考问题的新方法,但这仍然是一个非常常见的OO范例,并且通常值得使用。如果我想创建与这些交互的ViewControllers,它很有可能遵循相同的模式:
class CommonViewController:UIViewController {
var model:Common!
// common behavior to deal with the common behavior found in the Common superclass
}
class SubAViewController:CommonViewController {
var model:SubA!
// more methods to deal with the specializations that SubA provides
}
class SubBViewController:CommonViewController {
var model:SubB!
// more methods to deal with the specializations that SubA provides
}
同样,非常标准的构造。不幸的是,Swift的类型系统不允许它:
error: cannot override mutable property 'model' of type 'Common!' with covariant type 'SubA!'
var model:SubA!
有一个容易解决的问题吗?我能想到的最简单的方法是将子ViewControllers作为:
class SubAViewController:CommonViewController {
var subA:SubA {
get {
return self.model as! SubA
}
set {
self.model = newValue
}
}
// some behavior will need to use self.subA to get that type of data
}
class SubBViewController:CommonViewController {
var subB:SubB {
get {
return self.model as! SubB
}
set {
self.model = newValue
}
}
// some behavior will need to use self.subA to get that type of data
}
这增加了2个必须要做的工作方法以及我的一些子类方法必须引用self.subB
或self.subA
而不是{的约束。 {1}}。我开始研究如何使用协议和扩展来实现这一点,但我感觉我正在添加越来越多的箍来使解决方案成为我想要的。是否有一个更简单的解决方案可以与Swift一起使用来实现这种非常经典和常见的OO继承模式?
答案 0 :(得分:1)
总之,你不能这样做。您必须添加具有不同类型的新属性,并为getter和setter提供被覆盖的属性。 类似的案例可以在这里找到:Overriding superclass property with different type in Swift
答案 1 :(得分:1)
任何强类和静态类型的面向对象语言都不允许您尝试做的事情,不仅仅是在Swift中。
考虑一个函数f
来获取类型为CommonViewController
的对象。例如,此函数可以使用新值(类model
的实例)修改对象的变量Common
。
然后,您可以向f
传递SubAViewController
类型的值,这是合法的,因为其类型将是CommonViewController
的子类型。当f
为其属性model
分配Common
类型的新值时,这会违反model
内SubAViewController
的类型声明,这可能导致运行时间类型错误,这种语言不允许这样做。