Swift属性覆盖不起作用

时间:2014-09-30 03:21:19

标签: properties swift ios8 override

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

我在超级课程中提供了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
        }
    }
}

我究竟做错了什么?

2 个答案:

答案 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;
}
相关问题