2

我想知道 swift 语言中的这种行为是否记录在任何地方。我在官方文档中没有找到。最好用代码表示:

var testBacking = CGPoint(x: 3, y: 5)
var testPoint:CGPoint {
    get {
        print("getter called")
        return testBacking
    } set {
        print("setter called with newValue = \(newValue)")
        testBacking = newValue
    }
}
testPoint.x = 10 //  getter called
                 //  setter called with newValue = (10.0, 5.0)

如您所见,我只是设置x计算结构的组件,testPoint这样做时,swift会自动首先调用getter并拉出y组件并构建一个完整的结构,然后将其作为newValue传递给setter。这似乎是适当的行为。我的问题是:这种行为记录在哪里?我错过了它,还是根本没有提到它?

4

1 回答 1

1

理解这一点的方法是考虑一个类似但更简单的案例,而不需要额外的复杂性。让我们谈谈这个:

struct S {
    var name = "matt"
}
var s = S()
s.name = "mogelbuster"

这是如何运作的?当我们设置时会发生什么s.name?首先,拉出 的当前值s;然后,我们设置它的name属性;然后,我们将值设置s为这个新结构。(您可以通过在 上放置一个 setter 观察者来轻松确认最后一部分s。)

通过引用设置结构的属性,然后涉及获取引用的值(结构)、设置属性以及使用新结构设置引用的值。那是因为 struct 是一个值类型。它不能就地突变,因此通过对结构的引用设置属性涉及设置到引用中。

您正在做testPoint的只是同一过程的计算变量版本。仅仅谈论的行为testPoint.x意味着我们必须得到 testBacking,以找出它是什么。因此,调用了 getter。然后你设置成testPoint.x,从而调用设置器将新值写回testBacking


请注意,如果我们使用一个类,同样的事情就不会成立。这是原始示例的变体:

    class PointHolder {
        var point = CGPoint(x:3, y:5)
        var x : CGFloat {
            get { return point.x }
            set { point.x = newValue }
        }
    }
    var testBacking = PointHolder()
    var testPoint:PointHolder {
        get {
            print("getter called")
            return testBacking
        } set {
            print("setter called with newValue = \(newValue)")
            testBacking = newValue
        }
    }
    testPoint.x = 10 // getter called, but _not_ setter

在最后一行中,testPointsetter没有被调用——因为类实例是一个引用类型并且是可变的。testBacking没有设置就改变了,因为testBacking我们说的时候得到testPoint.x的,getter被调用,是一个引用;对此进行更改会更改事物所testBacking指向的内容,而无需对其进行设置。

于 2017-03-26T19:22:26.083 回答