Swift:为什么带有setter的变量也必须有一个getter?

Jos*_*Mum 7 getter setter swift

快速问题:为什么?


语境:

我使用Swinject依赖注入将small-s单例模型类添加到我的视图中:

defaultContainer.registerForStoryboard( MyViewController.self )
{
    responder, viewController in
    viewController.proxy = responder.resolve( MyProxy.self )!
}
Run Code Online (Sandbox Code Playgroud)

我想通过使用计算属性来防止意外覆盖此单例实例的风险:

private var _proxy: MyProxy!

var proxy: MyProxy 
{ 
    set { if _proxy == nil { _proxy = newValue } } 
}
Run Code Online (Sandbox Code Playgroud)

但.我不能.因为我还必须宣布一个吸气剂.

令人沮丧!

现在我使用以下hack.但真的......

var proxy: MyProxy?
{
    get { return nil }
    set { if _proxy == nil && newValue != nil { _proxy = newValue } }
}
Run Code Online (Sandbox Code Playgroud)

mat*_*elo 9

快速回答" 为什么? ":

get(或set)添加到属性后,它将变为Computed Property.计算属性可能是只读的,因此只需要一个getter,但它们可能不是只写的.因此,如果您向属性添加setter,则将其转换为计算机属性,因此您还必须添加getter.

编辑:以下评论,为什么计算属性是只读的,但不是只写的?

我找不到官方文档来支持这一点,所以以下解释完全基于我的逻辑观点:

计算属性不会在其变量上存储实际数据 ; 相反,他们计算要显示的数据.

var a:Int = 5 // Stored property
var timesTen:Int { // Computed Property
    get {
        return a * 10
    }
}
Run Code Online (Sandbox Code Playgroud)

从上面的示例:a是一个存储属性.因此,它的get方法自动返回a值.现在想一想timesTen:它的价值是什么?由于它不在timesTen变量中存储任何值,因此必须告诉计算属性如何以及从何处读取其"值".这就是为什么你不能将计算属性用于只写目的.


解决方法/如何避免它

对于简单属性,您可以使用didSetwillSet达到预期目的:

var proxy: MyProxy?
{
    willSet { if _proxy == nil && newValue != nil { _proxy = newValue } }
}
Run Code Online (Sandbox Code Playgroud)

如果您使用的是Swift 2.x,则可以使用该guard语句获得更清晰的代码:

var proxy: MyProxy?
{
    willSet { 
         guard (_proxy == nil && newValue != nil) else { return }
         _proxy = newValue
    }
}
Run Code Online (Sandbox Code Playgroud)

另一个观察

如果_proxy不是必须的话,private你可以完全删除它,只使用一个变量/属性而不是两个:

var proxy: MyProxy!
{
    willSet { 
         guard (proxy == nil && newValue != nil) else { return }
         // By not preventing `willSet` to continue, `newValue` will automatically assigned to `proxy`
    }
}
Run Code Online (Sandbox Code Playgroud)