関数noise
をオーバーライドすると、関数は新しい関数に置き換えられます。しかし、オブザーバーでプロパティをオーバーライドすると、古い値と新しい値の両方が実行されます。
遊び場で:
class Vehicle {
func noise(sound: String) {
println("Vehicle sound sounds like \(sound)")
}
}
class Train: Vehicle {
override func noise(sound: String) {
println("A train does: \(sound)")
}
}
出力:
var oldTrain = Train()
bulletTrain.noise("tjoek tjoek") // Prints: "A train does: tjoek tjoek"
しかし、オブザーバーを持つプロパティで同じことをすると:
遊び場で:
class Foo {
var something: Int! {
didSet {
println("vroom")
}
}
}
class Bar: Foo {
override var something: Int! {
didSet {
println("toot toot")
}
}
}
出力:
var foobar = Bar()
foobar.something = 3 // Prints: "vroom" & "toot toot"
では、プロパティをオブザーバーでオーバーライドする方法と、古い値が実行されないようにする方法を教えてください。
プロパティのset
とget
の部分をオーバーライドして、println
をそこに移動できます。このようにSwiftは元のコードを呼び出しません-superを呼び出さない限り)。
class Foo {
private var _something: Int!
var something: Int! {
get {
return _something
}
set {
_something = newValue
println("vroom")
}
}
}
class Bar: Foo {
override var something: Int! {
get {
return _something
}
set {
_something = newValue
println("toot toot")
}
}
}
しかし、それはきれいではありません。
ここに、より優れた、よりシンプルなソリューションがあります。
class Foo {
var something: Int! {
didSet {
somethingWasSet()
}
}
func somethingWasSet() {
println("vroom")
}
}
class Bar: Foo {
override func somethingWasSet() {
println("toot toot")
}
}
didSet
を「オーバーライド」する方法がないため、残っているのは、その目的のために特別に作成された2次関数をオーバーライドしていることです。
Swiftのドキュメント から
スーパークラスの初期化子が呼び出された後、サブクラスの初期化子でプロパティが設定されると、スーパークラスのプロパティのwillSetおよびdidSetオブザーバーが呼び出されます。スーパークラス初期化子が呼び出される前に、クラスが独自のプロパティを設定している間は呼び出されません。
サブクラスのオブザーバーは、スーパークラスで定義されたオブザーバーにのみ追加されます。
公式ドキュメントから: 上書き
上書きプロパティ
継承されたインスタンスまたはタイププロパティをオーバーライドして、そのプロパティに独自のカスタムゲッターおよびセッターを提供したり、またはプロパティオブザーバーを追加してオーバーライドするプロパティを有効にしたりできます。基本となるプロパティ値がいつ変化するかを観察します。