在Swift中覆盖存储的属性

我注意到编译器不会让我用另一个存储的值覆盖存储的属性(这看起来很奇怪):

class Jedi { var lightSaberColor = "Blue" } class Sith: Jedi { override var lightSaberColor = "Red" // Cannot override with a stored property lightSaberColor } 

但是,我可以用一个计算的属性来做到这一点:

 class Jedi { let lightSaberColor = "Blue" } class Sith: Jedi { override var lightSaberColor : String{return "Red"} } 

为什么我不能给它另一个价值?

为什么用存储的财产压倒一个可憎的事物,并用计算出来的一个犹太人来做呢? 他们在想什么?

为什么我不允许给它另一个价值?

你绝对可以给inheritance的财产一个不同的价值。 你可以做到这一点,如果你初始化一个构造函数的初始值,并从派生类传递一个不同的值:

 class Jedi { // I made lightSaberColor read-only; you can make it writable if you prefer. let lightSaberColor : String init(_ lsc : String = "Blue") { lightSaberColor = lsc; } } class Sith : Jedi { init() { super.init("Red") } } let j1 = Jedi() let j2 = Sith() println(j1.lightSaberColor) println(j2.lightSaberColor) 

重写财产不等于给它一个新的价值 – 这更像是给一个类别一个不同的财产。 事实上,这就是当你重写一个计算属性时会发生什么情况:计算基类中属性的代码被计算派生类中该属性重写的代码所替代。

[是否]可能重写实际存储的属性,即lightSaberColor有一些其他的行为?

除了观察者,存储的属性没有行为,所以没有什么可以覆盖的。 通过上述机制赋予财产不同的价值。 这正是问题中的例子试图用不同的语法来实现的。

对我来说,你的例子在Swift 3.0.1中不起作用。

进入操场这个代码:

 class Jedi { let lightsaberColor = "Blue" } class Sith: Jedi { override var lightsaberColor : String{return "Red"} } 

在Xcode编译时引发错误:

不能用'var'的getter覆盖不可变的'let'属性'lightsaberColor'

不,您不能更改存储的属性的types。 Liskov替代原则迫使你允许在需要超类的地方使用子类。

但是,如果将其更改为var并因此将该set添加到计数属性中,则可以使用相同types的计数属性覆盖存储的属性。

 class Jedi { var lightsaberColor = "Blue" } class Sith: Jedi { override var lightsaberColor : String { get { return "Red" } set { // nothing, because only red is allowed } } } 

这是可能的,因为从存储属性切换到计算属性是有意义的。

但用存储的var属性覆盖存储的var属性是没有意义的,因为你可以改变属性的值。

但是,您可以不使用存储的属性覆盖存储的属性。


我不会说西斯是绝地的–P。 所以很明显,这是行不通的。

您可能想要为该属性分配另一个值:

 class Jedi { var lightSaberColor = "Blue" } class Sith: Jedi { override init() { super.init() self.lightSaberColor = "Red" } } 

对于Swift 4,从苹果的文档 :

您可以重写inheritance的实例或types属性以为该属性提供您自己的自定义getter和setter,或者添加属性观察器以使重写属性能够观察基础属性值何时更改。

 class SomeClass { var hello = "hello" } class ChildClass: SomeClass { override var hello: String { set { super.hello = newValue } get { return super.hello } } }