Swift编程语言允许子类重写具有相同类型T的超类属性,但不能替代具有不同类型S的超类属性,即使S衍生自T也不例外。这是https://docs.swift.org/swift-book/LanguageGuide/Inheritance.html的引号:
您必须始终声明您的属性的名称和类型 覆盖,使编译器能够检查您的覆盖 匹配具有相同名称和类型的超类属性。
在重写方法时,Swift确实允许重写的子类方法返回从超类方法的返回类型派生的类型。
我的问题是:禁止子类覆盖具有从T派生的类型S的超类属性的动机是什么?
答案 0 :(得分:1)
这实际上并不限于Swift。这将破坏多态性。请参见wikipedia: Subtyping
上的子类型化规则基本上,请考虑以下示例:
class A {
var x: NSObject?
}
class B: A {
override var x: NSNumber?
}
并考虑:
let b = B(x: 1)
let a: A = b // it's a subclass, polymorphism allows to assign it to A
a.x = NSObject() // let's assign NSObject() because A.x takes NSObject
print(b.x) // b.x should be a NSNumber now but we have assigned a NSObject?
您必须认识到,属性是两个函数的组合,即setter和getter。您可以在getter(函数的返回值)中添加更特定的类型(协变类型),但不能对setter进行此操作(重写函数的参数需要互变)。
这还告诉您这将与readonly属性一起工作:
class A {
var x: NSObject? {
return NSObject()
}
}
class B: A {
override var x: NSNumber? {
return NSNumber()
}
}