Swift属性覆盖不起作用

Der*_*328 21 overriding properties swift ios8

当我尝试覆盖属性时,我收到错误"无法覆盖具有只读属性的可变属性"

我已经在超类中提供了get和set.

class Card {
    var contents:String {
        get {
            return self.contents
        }
        set {
            self.contents = newValue
        }
    }
    init() {
        self.contents = ""
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的Subclass,我试图覆盖"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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?

Mik*_*e S 30

如果您要覆盖的属性同时具有getter和setter,则还需要在子类中同时提供这两个属性.这是Swift语言指南(强调我的)中的相关部分:

通过在子类属性覆盖中提供getter和setter,可以将继承的只读属性作为读写属性提供.但是,您不能将继承的读写属性显示为只读属性.

如果您没有对值进行任何特殊操作,那么您通常希望将设置的值传递给基类:

set {
    super.contents = newValue
}
Run Code Online (Sandbox Code Playgroud)

你也可以用一个空的setter来丢弃这个值(虽然我想不出有理由这么做):

set { }
Run Code Online (Sandbox Code Playgroud)

我还想指出contents你的Card班级属性中有一个无限循环.当你这样做:

get {
    return self.contents
}
Run Code Online (Sandbox Code Playgroud)

你实际上只是再次调用相同的getter,创建一个无限循环; 你对二传手做同样的事情.Swift不会像Objective-C那样自动为您的属性创建ivars,因此您需要自己创建它们.创建该属性的更合适的方法是执行以下操作:

class Card {
    private var _contents: String
    var contents: String {
        get {
            return _contents
        }
        set {
            _contents = newValue
        }
    }
    init() {
        _contents = ""
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,由于除了_contents在setter和getter中设置和返回之外你没有做任何其他事情,你可以将其简化为:

class Card {
    var contents: String = ""
    init() {

    }
}
Run Code Online (Sandbox Code Playgroud)

注意: contents也可能是使用optional(String?)并将其设置为nil而不是将其初始化为空字符串的良好候选者.


Dai*_*Dai 4

编译器错误消息相当简单:Card's contentsproperty is mutable,也就是说它set除了方法之外还有一个方法get

您的重写仅添加一个get方法,您还需要添加一个set方法。

我想这就是你想要的:

set(newValue) {
    rankStrings[Int(self.rank)] = newValue;
}
Run Code Online (Sandbox Code Playgroud)