ios Swift 编程:存储属性中的 getter/setter

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24114732/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 00:42:22  来源:igfitidea点击:

Swift Programming: getter/setter in stored property

iosswift

提问by bohanl

How do I overwrite the setter of stored property in Swift?

如何覆盖 Swift 中存储属性的设置器?

In Obj-C, I can overwrite its setter, but Swift doesn't seem to be happy about getter/setters being used for stored property.

在 Obj-C 中,我可以覆盖它的 setter,但 Swift 似乎对用于存储属性的 getter/setter 并不满意。

Say I have a Cardclass with a property called rank. I don't want the client to give it any invalid value, therefore, in objective-C, I can overwrite setRankso that it performs additional check. But willSetin Swift doesn't seem to help because newValueis constant and it makes no sense to assign rankbecause setter will be called in a loop.

假设我有一个Card名为rank. 我不希望客户端给它任何无效的值,因此,在 Objective-C 中,我可以覆盖setRank以便它执行额外的检查。但是willSet在 Swift 中似乎没有帮助,因为newValue它是常量并且分配没有意义,rank因为 setter 将在循环中被调用。

回答by Mihai Fratu

Ok. Reading through Apples documentation on Swift I found this:

好的。阅读有关 Swift 的 Apples 文档,我发现了这一点

If you assign a value to a property within its own didSet observer, the new value that you assign will replace the one that was just set.

如果你在它自己的 didSet 观察者中为一个属性赋值,你分配的新值将替换刚刚设置的值。

So all you have to do is this:

所以你所要做的就是:

var rank: Int = 0 {
    didSet {
        // Say 1000 is not good for you and 999 is the maximum you want to be stored there
        if rank >= 1000  {
            rank = 999
        }
    }
}

回答by Joseph Mark

You can't override get/setfor a stored property but you can use property observers willSet/didSet:

您不能为存储的属性覆盖get/ set,但可以使用属性观察者willSet/ didSet

var totalSteps: Int = 0 {
    willSet(newTotalSteps) {
        println("About to set totalSteps to \(newTotalSteps)")
    }
    didSet {
        if totalSteps > oldValue  {
            println("Added \(totalSteps - oldValue) steps")
        }
    }
}

The default parameter names are newValuefor willSetand oldValuefor didSet, or you can name them yourself as in willSet(newTotalSteps).

默认参数名称为newValueforwillSetoldValuefor didSet,或者您可以自己将它们命名为 in willSet(newTotalSteps)

回答by user3675131

get and set are for computed properties (they don't have any backing store). (In my opinion, the keyword 'var' is confusing here)

get 和 set 用于计算属性(它们没有任何后备存储)。(在我看来,关键字“var”在这里令人困惑)

  • willSet and didSet are called for an instance variable (Use didSet to override any changes)
  • set and get are purely for computed properties
  • 为实例变量调用 willSet 和 didSet(使用 didSet 覆盖任何更改)
  • set 和 get 纯粹用于计算属性

回答by Jim Driscoll

If you don't want to use didSet, which has the problem that the property's value is temporarily wrong, you should wrap a computed property around it.

如果你不想使用 didSet,它有属性值暂时错误的问题,你应该在它周围包裹一个计算属性。

private var _foo:Int = 0
var foo:Int {
    get {
        return _foo
    }
    set {
        if(newValue > 999) {
            _foo = 999
        } else {
            _foo = newValue
        }
    }
}

Or:

或者:

private var _foo:Int = 0
var foo:Int {
    get {
        return _foo
    }
    set {
        guard newValue <= 999 else {
            _foo = 999
            return
        }
        _foo = newValue
    }
}

回答by Mike Rapadas

Simplified Example:

简化示例:

class Shape {
    var sideLength: Double {
    get {
        return self.sideLength
    }
    set {
        // Implement the setter here.
        self.sideLength = newValue
    }
    }
}

Full example

完整示例

Check out perimeterin this example.

perimeter在这个例子中查看。

Excerpt From: Apple Inc. “The Swift Programming Language.” iBooks. https://itun.es/us/jEUH0.l

摘自:Apple Inc. “The Swift Programming Language”。电子书。https://itun.es/us/jEUH0.l

class EquilateralTriangle: NamedShape {
    var sideLength: Double = 0.0

    init(sideLength: Double, name: String) {
        self.sideLength = sideLength
        super.init(name: name)
        numberOfSides = 3
    }

    var perimeter: Double {
    get {
        return 3.0 * sideLength
    }
    set {
        sideLength = newValue / 3.0
    }
    }

    override func simpleDescription() -> String {
        return "An equilateral triagle with sides of length \(sideLength)."
    }
}
var triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle")
triangle.perimeter
triangle.perimeter = 9.9
triangle.sideLength”