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

时间:2016-01-08 12:01:07

标签: swift setter 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 } } 
}

但是。我不能。因为我必须也宣布一个吸气剂。

令人沮丧!

目前我正在使用以下黑客攻击。但是真的......

var proxy: MyProxy?
{
    get { return nil }
    set { if _proxy == nil && newValue != nil { _proxy = newValue } }
}

3 个答案:

答案 0 :(得分:8)

快速回答快速问题“为什么?”:

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

编辑:在评论之后, 为什么计算属性只能是只读的,而不是只写的?

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

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

var a:Int = 5 // Stored property
var timesTen:Int { // Computed Property
    get {
        return a * 10
    }
}

从上面的示例中:a存储的属性。因此,其get方法会自动返回a的值。现在想起timesTen:它有什么价值?由于它不会在timesTen变量中存储任何值,因此必须告知计算属性从读取其“值”的方式和位置。这就是为什么你不能将计算属性用于只写目的。

解决方法/如何避免

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

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,您可以完全删除它,只使用一个变量/属性而不是两个:

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

答案 1 :(得分:1)

为什么你不能在你的吸气器中返回_proxy?那有什么关系?如果您害怕暴露您的getter,您可以将getter设置为private,从而仅在包含类中公开它。

private(get) var proxy: MyProxy? {
  set { if _proxy == nil && newValue != nil { _proxy = newValue } }
}

答案 2 :(得分:0)

目前,您只能使用属性观察者didSetwillSet