2014-11-01 258 views
52

重寫一個存儲的屬性,我注意到,編譯器不會讓我重寫與其他存儲的數據進行存儲的屬性(這似乎很奇怪):斯威夫特

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"} 

} 

爲什麼我不允許給它另一個值?

爲什麼用存儲的屬性重寫一個可憎的事物,並用一個計算出來的一個猶太人來做呢?他們在想什麼?

+0

[重寫與不同類型的超類屬性在Swift]藥物的可能重複(http://stackoverflow.com/questions/24094158/overriding-superclass-property-with-different-type-in​​-swift) – 2015-09-18 14:56:16

回答

34

爲什麼我不能給它另一個價值?

您絕對被允許給繼承的屬性一個不同的值。你可以做到這一點,如果你初始化一個構造函數是初始值的屬性,並從派生類中傳遞不同的值:

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有其他一些行爲?

除了觀察者,存儲的屬性沒有行爲,所以沒有什麼可以覆蓋的。通過上述機制賦予財產不同的價值。這正是問題中的例子試圖用不同的語法來實現的。

+2

@MaxMacLeod除了觀察者,存儲的屬性沒有行爲,所以沒有什麼可以覆蓋的。他想給存儲的屬性在子類中提供一個不同的值,但他不確定實現它的機制。答案解釋瞭如何在Swift中完成。對於遲到的回覆,我感到很抱歉,看起來你的評論引起了足夠的混淆以吸引低價提名,所以我決定解釋發生了什麼。 – dasblinkenlight 2017-05-09 13:48:44

10

你可能想另一個值assing的財產:

class Jedi { 
    var lightSaberColor = "Blue" 
} 


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

同樣適用於上述評論 – 2015-09-18 14:55:15

17

對我來說,你的例子並不在斯威夫特3.0.1工作。

在操場上輸入此代碼:

class Jedi { 
    let lightsaberColor = "Blue" 
} 

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

在Xcode在編譯時拋出錯誤:

不能覆蓋一成不變「讓」屬性「lightsaberColor」與「變種」

的消氣

不,您不能更改存儲的屬性的類型。 Liskov替代原則強制您允許在需要超類的地方使用子類。

但是,如果將其更改爲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。因此很明顯,這是行不通的。

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

雖然此代碼段可能會解決問題,但[包括解釋](http://meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers)確實有助於提高您的帖子的質量。請記住,您將來會爲讀者回答問題,而這些人可能不知道您的代碼建議的原因。 – DimaSan 2017-03-15 11:22:37

4

對於斯威夫特4,從Apple's documentation

您可以覆蓋繼承的實例或類型屬性來提供該屬性 自己的自定義getter和setter,或者添加 財產觀察員啓用重寫屬性以觀察 基礎屬性值是否更改。