设置 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)
如您所见,我只设置了计算结构 testPoint
的 x
组件,这样做时,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
指向 而无需 设置。
我想知道 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)
如您所见,我只设置了计算结构 testPoint
的 x
组件,这样做时,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
指向 而无需 设置。