Swift:为什么带有 setter 的变量也必须有 getter?
Swift: Why does a variable with a setter must also have a getter?
快速提问:为什么?
上下文:
我正在使用 Swinject 依赖注入将 small-s 单例模型 类 添加到我的视图中,因此:
defaultContainer.registerForStoryboard( MyViewController.self )
{
responder, viewController in
viewController.proxy = responder.resolve( MyProxy.self )!
}
我想通过使用计算 属性 来防止意外覆盖此单例实例的风险:
private var _proxy: MyProxy!
var proxy: MyProxy
{
set { if _proxy == nil { _proxy = newValue } }
}
但是。我不能。因为我必须同时声明一个getter.
令人沮丧!
目前我正在使用以下 hack。但真的...
var proxy: MyProxy?
{
get { return nil }
set { if _proxy == nil && newValue != nil { _proxy = newValue } }
}
为什么你不能 return _proxy
在你的 getter 中?那有什么关系?如果你害怕暴露你的 getter ,你可以将你的 getter 设置为私有,这样只在包含 class.
的地方暴露它
private(get) var proxy: MyProxy? {
set { if _proxy == nil && newValue != nil { _proxy = newValue } }
}
目前你只能使用属性观察者didSet
或willSet
快速问题“为什么?”的快速回答:
将 get
(或 set
)添加到 属性 后,它会变成 Computed Property。计算属性可能是read-only,因此只需要get
之三,但它们可能不 为 write-only。所以如果你把一个set
ter加到一个属性,你就把它变成了一台电脑属性因此你必须 也添加一个 getter。
编辑: 根据评论,为什么计算属性可以是 read-only,而不是 write-only?
我找不到官方文档来支持这一点,所以以下解释完全基于我的逻辑观点:
计算属性不在其变量上存储实际数据;相反,他们 计算 要显示的数据。
var a:Int = 5 // Stored property
var timesTen:Int { // Computed Property
get {
return a * 10
}
}
从上面的例子来看:a
是 Stored 属性。因此,它的get
方法自动取returnsa
的值。现在想想timesTen
:它的值是多少?由于它不在 timesTen
变量中存储任何值,因此您 必须告诉计算 属性 如何以及从何处从 读取其 "value"。所以这就是为什么您不能将计算的 属性 用于 writing-only 目的。
解决方法/如何避免
对于简单的属性,您可以使用 didSet
或 willSet
来达到预期目的:
var proxy: MyProxy?
{
willSet { if _proxy == nil && newValue != nil { _proxy = newValue } }
}
如果您正在使用 Swift 2.x,您可以使用 guard
语句来获得更清晰的代码:
var proxy: MyProxy?
{
willSet {
guard (_proxy == nil && newValue != nil) else { return }
_proxy = newValue
}
}
另一个观察结果
如果_proxy
不需要成为private
,您可以完全删除它,只使用一个variable/property而不是两个:
var proxy: MyProxy!
{
willSet {
guard (proxy == nil && newValue != nil) else { return }
// By not preventing `willSet` to continue, `newValue` will automatically assigned to `proxy`
}
}
快速提问:为什么?
上下文:
我正在使用 Swinject 依赖注入将 small-s 单例模型 类 添加到我的视图中,因此:
defaultContainer.registerForStoryboard( MyViewController.self )
{
responder, viewController in
viewController.proxy = responder.resolve( MyProxy.self )!
}
我想通过使用计算 属性 来防止意外覆盖此单例实例的风险:
private var _proxy: MyProxy!
var proxy: MyProxy
{
set { if _proxy == nil { _proxy = newValue } }
}
但是。我不能。因为我必须同时声明一个getter.
令人沮丧!
目前我正在使用以下 hack。但真的...
var proxy: MyProxy?
{
get { return nil }
set { if _proxy == nil && newValue != nil { _proxy = newValue } }
}
为什么你不能 return _proxy
在你的 getter 中?那有什么关系?如果你害怕暴露你的 getter ,你可以将你的 getter 设置为私有,这样只在包含 class.
private(get) var proxy: MyProxy? {
set { if _proxy == nil && newValue != nil { _proxy = newValue } }
}
目前你只能使用属性观察者didSet
或willSet
快速问题“为什么?”的快速回答:
将 get
(或 set
)添加到 属性 后,它会变成 Computed Property。计算属性可能是read-only,因此只需要get
之三,但它们可能不 为 write-only。所以如果你把一个set
ter加到一个属性,你就把它变成了一台电脑属性因此你必须 也添加一个 getter。
编辑: 根据评论,为什么计算属性可以是 read-only,而不是 write-only?
我找不到官方文档来支持这一点,所以以下解释完全基于我的逻辑观点:
计算属性不在其变量上存储实际数据;相反,他们 计算 要显示的数据。
var a:Int = 5 // Stored property
var timesTen:Int { // Computed Property
get {
return a * 10
}
}
从上面的例子来看:a
是 Stored 属性。因此,它的get
方法自动取returnsa
的值。现在想想timesTen
:它的值是多少?由于它不在 timesTen
变量中存储任何值,因此您 必须告诉计算 属性 如何以及从何处从 读取其 "value"。所以这就是为什么您不能将计算的 属性 用于 writing-only 目的。
解决方法/如何避免
对于简单的属性,您可以使用 didSet
或 willSet
来达到预期目的:
var proxy: MyProxy?
{
willSet { if _proxy == nil && newValue != nil { _proxy = newValue } }
}
如果您正在使用 Swift 2.x,您可以使用 guard
语句来获得更清晰的代码:
var proxy: MyProxy?
{
willSet {
guard (_proxy == nil && newValue != nil) else { return }
_proxy = newValue
}
}
另一个观察结果
如果_proxy
不需要成为private
,您可以完全删除它,只使用一个variable/property而不是两个:
var proxy: MyProxy!
{
willSet {
guard (proxy == nil && newValue != nil) else { return }
// By not preventing `willSet` to continue, `newValue` will automatically assigned to `proxy`
}
}