Lazy Var vs Let

若如初见. 提交于 2019-11-30 10:42:36

This is the latest scripture from the Xcode 6.3 Beta / Swift 1.2 release notes:

let constants have been generalized to no longer require immediate initialization. The new rule is that a let constant must be initialized before use (like a var), and that it may only be initialized: not reassigned or mutated after initialization.

This enables patterns like:

let x: SomeThing
if condition {
    x = foo()
} else {
    x = bar()
}

use(x)

which formerly required the use of a var, even though there is no mutation taking place. (16181314)

Evidently you were not the only person frustrated by this.

Swift book has the following note:

You must always declare a lazy property as a variable (with the var keyword), because its initial value might not be retrieved until after instance initialization completes. Constant properties must always have a value before initialization completes, and therefore cannot be declared as lazy.

This makes sense in the context of implementing the language, because all constant stored properties are computed before initialization of an object has finished. It does not mean that the semantic of let could have been changed when it is used together with lazy, but it has not been done, so var remains the only option with lazy at this point.

As far as the two choice that you presented go, I would decide between them based on efficiency:

  • If accessing the value of a property is done rarely, and it is expensive to compute upfront, I would use var lazy
  • If the value is accessed in more than 20..30% of cases or it is relatively inexpensive to compute, I would use let

Note: I would further optimize your code to push the conditional into CGFloat initializer:

let fontSize : CGFloat = CGFloat(someCase  ? 30 : 17)

As dasblinkenlight points out lazy properties should always be declared as variables in Swift. However it is possible make the property read-only so it can only be mutated from within the source file that the Entity was defined in. This is the closest I can get to defining a "lazy let".

private(set) lazy var fontSize: CGFloat = {
    if someCase {
        return 30
    } else {
        return 17
    }
}()
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!