Swift 中的惰性只读属性

Posted

技术标签:

【中文标题】Swift 中的惰性只读属性【英文标题】:Lazy readonly property in Swift 【发布时间】:2014-11-20 18:58:32 【问题描述】:

在使用 Swift 时,我尝试编写一个只读且惰性的初始化属性。我很快就写了那行代码,只是为了知道这是不允许的。

// no valid Swift code.
lazy let foo : Int =  return 42 ()

您必须将惰性属性声明为var。 这本 swift 书清楚地指出, let with lazy 是不可能的:

“您必须始终将惰性属性声明为变量(使用 var 关键字),因为在实例初始化完成之前可能无法检索其初始值。常量属性在初始化完成之前必须总是有一个值,因此不能被声明为惰性。”

假设我想在 swift 中有一个只读的惰性属性。存档的最佳方式是什么?

【问题讨论】:

【参考方案1】:

如果在这种特定情况下 readonly 和 private 是您的同义词,那么您可以通过显式声明 setter 将其设为私有:

private(set) lazy var foo : Int =  return 42 ()

这是不变性和惰性之间的良好折衷。

【讨论】:

私人二传手对我来说已经足够了。我也经常在 C# 中使用这种模式。 它不是一个 getter,它是一个惰性实例化闭包,但也没有必要,因为它不包含任何逻辑。这就是为什么private(set) lazy var foo = 42 会以同样的方式工作的原因。 这应该可以,但它不行:gist.github.com/4821ffb13e110dfeb027 注意:这也是一个可能的安全问题。 @Barry:我认为代码在同一个文件(或游乐场)中 - 如果是,请记住,private 不会将属性或方法设为类/结构的私有,但是文件私有,即可以从文件内的任何地方访问,但不能从任何地方访问 @cumanzor 没错,private 是把它设为私有类型,fileprivate 一样,但可以从使用它的文件中访问。【参考方案2】:

您还可以使用延迟初始化的私有后备变量:

var foo : Int  return _foo 
private lazy var _foo :Int =  return 42 ()

【讨论】:

虽然你的答案是正确的,但我更喜欢 Antonios 的答案,因为它不会引入其他属性。 虽然接受的答案目前不起作用,但确实如此。 @Barry 接受的答案现在有效(从 Xcode 7.1 开始)【参考方案3】:

可以使用计算属性和私有结构来做到这一点。静态 var 值不需要惰性关键字,因为将块的结果分配给它是隐式惰性的。

var foo: Int 
    struct Holder 
        static var value =  return 42 ()
    
    return Holder.value

【讨论】:

我认为这很聪明,在某些情况下很有用,但遗憾的是,当计算值依赖于“self”对象时它就没有用了,因为 swift 不允许内部结构关闭在外部范围内。 @Daniel 你说得很好,但是这种方法在问题的上下文中非常有效。【参考方案4】:

您需要在初始化时声明该属性以使其不可变。

class Class 
  let foo: Int
  init() 
    self.foo = 42
  

【讨论】:

以上是关于Swift 中的惰性只读属性的主要内容,如果未能解决你的问题,请参考以下文章

关于swift中的只读属性

在 Swift 中定义一个只读属性

如何在 Swift 中覆盖 Objective-C 的只读属性?

如何在 Swift 中覆盖 Objective-C 的只读属性?

类的惰性属性

Swift get和set方法以及只读属性(计算型属性,本身不保存数据,都是通过计算获得结果)