2014-11-01 395 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,或者添加 财产观察员启用重写属性以观察 基础属性值是否更改。