设置 Swift 计算结构的一部分

Setting Part of Swift Computed Structure

我想知道 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)

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

理解这一点的方法是考虑一个类似但更简单的案例,没有额外的并发症。就说这个吧:

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

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

通过引用设置结构的 属性,然后涉及获取引用的值(结构),设置 属性,并使用新结构设置引用的值。那是因为结构是 值类型 。它不能就地改变,因此通过引用结构来设置 属性 涉及设置引用。

您使用 testPoint 所做的只是同一过程的计算变量版本。仅仅说出 testPoint.x 就意味着我们必须 get testBacking,才能找出它是什么。因此, getter 被调用。然后你设置为 testPoint.x,从而调用 setter 将新值写回 testBacking


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

    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

在最后一行中,testPoint setter 未被调用 — 因为 class 实例是 引用类型 并且是可变的。 testBacking 在没有设置的情况下被更改,因为当我们说 testPoint.x 和 getter 被调用时,我们从 testBacking 得到的是一个参考;对此进行更改会将 testBacking 指向 而无需 设置。