【问题标题】:Correct use of lazy instantiation正确使用惰性实例化
【发布时间】:2017-01-19 10:12:53
【问题描述】:

我对惰性实例化的理解是应该在以下情况下使用它

  • 惰性属性可能需要也可能不需要初始化和/或
  • 属性的初始化可能很昂贵和/或
  • 属性的初始化取决于其他可能事先不知道的参数。

然而,我越来越多地遇到这样的代码 [伪代码]:

class SomeClass {
    lazy var itemSize: CGSize = { return CGSize(width: 80, height: 80) }()

    ....
    init() {
        [use itemSize for some init work]
    }
}

对我来说,这没有任何意义,因为 itemSize 总是需要被初始化,并不昂贵并且不依赖于任何未知属性。我错过了什么吗?

【问题讨论】:

  • 我认为这也很好,因为它允许您在小的懒惰代码块中设置任何内容,而不是一些拥有大量 viewDidLoad 的人:充满了配置其属性的不同方面。跨度>
  • @SeanLintern88 该代码块与其懒惰无关。任何属性都可以用这样的块来实例化。我经常使用...let blah: UILabel = {...}() 来设置其他类需要访问的属性。它甚至可以在函数内部使用来创建变量等......不仅仅是属性。
  • 另一个相关见解:lazy 实例属性可能不是不可变的。然而,所有 type 属性(static .../class ...)默认为lazy,您可以自然地实现不可变类型属性。于是就有了lazy不可变属性,即不可变类型属性。

标签: swift lazy-initialization


【解决方案1】:

你说的很对。

在这种特殊情况下,不需要延迟实例化。

你所说的情况也是正确的。

但是,在这种情况下使用惰性实例化应该不会产生任何巨大的不利影响。

但是,如果我看到它,我会将其更改为 let 并删除 lazy。 (特别是如果它在任何时候都没有发生变异)。

【讨论】:

  • 很遗憾lazy let 是非法的。
  • @matt 是的,我没说这不违法?所以我会使用let 而不是lazy。也许我会澄清这一点。
【解决方案2】:

实际上,您已经省略(或在第三个要点中省略了)lazy 实例属性的最常见原因:它们可以显式或隐式地引用 self,而普通实例属性则不能。

另一点:lazy 实例属性不必是定义和调用匿名函数,在您给出的愚蠢示例中,没有任何理由让它如此。这样做也可以:

lazy var itemSize: CGSize = CGSize(width: 80, height: 80) 

lazy 和 define-and-call 都很有用,而且经常一起使用,但不要混淆它们。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-09
  • 2020-04-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多