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

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

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

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

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

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

【问题讨论】:

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

    【讨论】:

      猜你喜欢
      • 2023-01-25
      • 2017-10-29
      • 2015-03-18
      • 1970-01-01
      • 2017-11-04
      • 2015-05-15
      • 2017-06-06
      • 2017-06-18
      • 1970-01-01
      相关资源
      最近更新 更多