当我尝试覆盖属性时,我收到错误“无法覆盖具有只读属性的可变属性”
我在超级课程中提供了get和set。
class Card {
var contents:String {
get {
return self.contents
}
set {
self.contents = newValue
}
}
init() {
self.contents = ""
}
}
这是我的子类,我试图覆盖“contents”属性。
class PlayingCard: Card {
override var contents:String { //<-- this is where I get the build error
get {
var rankStrings:Array<String> = PlayingCard.rankStrings()
return rankStrings[Int(self.rank)] + self.suit
}
}
}
我究竟做错了什么?
答案 0 :(得分:27)
如果您要覆盖的属性同时具有getter和setter,则还需要在子类中同时提供这两个属性。这是relevant part from the Swift language guide(强调我的):
您可以将继承的只读属性显示为读写 通过在子类中提供getter和setter来实现属性 属性覆盖。 然而,你不能提出遗传 读写属性为只读属性。
如果你没有对值做任何特殊的事情,那么你通常希望将设置的值传递给基类:
set {
super.contents = newValue
}
你也可以用一个空的setter来丢弃这个值(尽管我想不出有理由这么做):
set { }
我还想指出你contents
类的Card
属性中有一个无限循环。当你这样做时:
get {
return self.contents
}
你实际上只是再次调用相同的getter,创建一个无限循环;你对二传手做同样的事情。 Swift不会像Objective-C那样自动为您的属性创建ivars,因此您需要自己创建它们。创建该属性的更合适的方法是执行以下操作:
class Card {
private var _contents: String
var contents: String {
get {
return _contents
}
set {
_contents = newValue
}
}
init() {
_contents = ""
}
}
但是,由于除了在setter和getter中设置和返回_contents
之外没有做任何其他事情,您可以将其简化为:
class Card {
var contents: String = ""
init() {
}
}
注意: contents
也可能是使用可选项(String?
)并将其设置为nil
而非初始化的理想选择到一个空字符串。
答案 1 :(得分:4)
编译器错误消息非常简单:Card
的{{1}}属性可变,也就是说除了contents
之外还有set
方法get
方法。
您的覆盖只会添加get
方法,您还需要添加set
方法。
我认为这就是你想要的:
set(newValue) {
rankStrings[Int(self.rank)] = newValue;
}