コンパイラは、保存されたプロパティを別の保存された値で上書きさせないことに気付きました(奇妙に思えます):
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"}
}
別の値を与えることが許可されないのはなぜですか?
なぜ保存されたプロパティでオーバーライドするのが憎悪であり、計算されたコーシャでそれを行うのですか?彼らは何を考えているの?
なぜ別の値を与えることが許可されないのですか?
継承されたプロパティに異なる値を与えることは間違いなく許可されています。その初期値を取得するコンストラクターでプロパティを初期化し、派生クラスから異なる値を渡す場合、それを行うことができます。
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)
プロパティをオーバーライドすることは、新しい値を与えることと同じではなく、クラスに異なるプロパティを与えることに似ています。実際、計算されたプロパティをオーバーライドすると、それが起こります。基本クラスのプロパティを計算するコードは、派生クラスのそのプロパティのオーバーライドを計算するコードによってreplacedです。
実際に保存されているプロパティ、つまり
lightSaberColor
をオーバーライドすることは可能ですか?
オブザーバーを除き、保存されたプロパティには動作がないため、実際にオーバーライドするものはありません。上記のメカニズムにより、プロパティに異なる値を与えることができます。これは、異なる構文を使用して、質問の例が達成しようとしていることとまったく同じです。
私の場合、あなたの例はSwift 3.0.1では動作しません。
このコードを遊び場に入力しました:
class Jedi {
let lightsaberColor = "Blue"
}
class Sith: Jedi {
override var lightsaberColor : String {
return "Red"
}
}
Xcodeでコンパイル時にエラーをスローします。
不変の「let」プロパティ「lightsaberColor」を「var」のゲッターでオーバーライドできません
いいえ、保存されたプロパティのタイプを変更することはできません。 Liskov Substitution Principle forcesスーパークラスが必要な場所でサブクラスを使用できるようにします。
しかし、それをvar
に変更し、したがって、計算プロパティにset
を追加すると、同じタイプの計算プロパティで保存プロパティをオーバーライドできます。
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"
}
}
class SomeClass {
var hello = "hello"
}
class ChildClass: SomeClass {
override var hello: String {
set {
super.hello = newValue
}
get {
return super.hello
}
}
}
Swift 4の場合、 Appleのドキュメント から:
継承されたインスタンスまたは型プロパティをオーバーライドして、そのプロパティに独自のカスタムgetterおよびsetterを提供したり、プロパティオブザーバを追加して、基になるプロパティ値が変更されたときにオーバーライドプロパティが監視できるようにすることができます。
Swiftでは、残念ながらこれを行うことはできません。最適な代替手段は次のとおりです。
class Jedi {
private(set) var lightsaberColor = "Blue"
}
class Sith: Jedi {
override var lightsaberColor : String {
get {
return "Red"
}
}
}
ビューコントローラーに定数を設定するのと同じ問題がありました。
インターフェイスビルダーを使用してビューを管理しているため、init()
を使用できないため、基本クラスと継承クラスの両方で読み取り専用の計算変数を使用することを除いて、回避策は他の回答と同様でした。
class Jedi {
var type: String {
get { return "Blue" }
}
}
class Sith: Jedi {
override var type: String {
get { return "Red" }
}
}
関数を使用してオーバーライドすることもできます。直接的な答えではありませんが、このトピックを充実させることができます)
クラスA
override func viewDidLoad() {
super.viewDidLoad()
if shouldDoSmth() {
// do
}
}
public func shouldDoSmth() -> Bool {
return true
}
クラスB:A
public func shouldDoSmth() -> Bool {
return false
}