“打开实例”是什么意思?为什么有必要?
据我所知(这对我来说也是很新的)......
“包裹”一词意味着我们应该将可选变量视为礼物,包裹在闪亮的纸中,它可能(遗憾的是!)是空的.
当“包装”时,可选变量的值是一个具有两个可能值的枚举(有点像布尔值)。该枚举描述了变量是否拥有一个值(Some(T)
), 或不 (None
).
如果有一个值,则可以通过“展开”变量来获得该值(获取T
from Some(T)
).
How is john!.apartment = number73
不同于john.apartment = number73
? (转述)
如果您编写可选变量的名称(例如文本john
,没有!
),这是指“包装”枚举(Some/None),而不是值本身(T)。所以john
不是一个实例Person
,并且它没有apartment
member:
john.apartment
// 'Person?' does not have a member named 'apartment'
实际上Person
值可以通过多种方式展开:
- “强制展开”:
john!
(给出Person
值(如果存在),如果为 nil,则运行时错误)
- “可选绑定”:
if let p = john { println(p) }
(执行println
如果该值存在)
- “可选链”:
john?.learnAboutSwift()
(如果该值存在则执行这个虚构的方法)
我猜你会选择其中一种解包方式,具体取决于零情况下会发生什么以及发生的可能性有多大。这种语言设计强制显式处理 nil 情况,我认为这比 Obj-C 提高了安全性(在 Obj-C 中很容易忘记处理 nil 情况)。
Update:
感叹号也用在声明“隐式解包可选”的语法中。
在到目前为止的示例中,john
变量已声明为var john:Person?
,并且它是一个可选的。如果您想要该变量的实际值,则必须使用上述三种方法之一将其解包。
如果它被声明为var john:Person!
相反,该变量将是隐式解包可选(请参阅 Apple 书中带有此标题的部分)。访问值时无需解开此类变量,并且john
无需额外语法即可使用。但苹果公司的书中说:
当变量稍后有可能变为 nil 时,不应使用隐式展开的选项。如果需要在变量的生命周期内检查 nil 值,请始终使用普通的可选类型。
Update 2:
文章《有趣的 Swift 功能迈克·阿什 (Mike Ash) 的文章为可选类型提供了一些动力。我认为这是很棒、清晰的写作。
Update 3:
另一篇关于的有用文章隐式解包可选用于感叹号:“斯威夫特和最后一英里” 作者:Chris Adamson。文章解释说,这是 Apple 的一项实用措施,用于声明其 Objective-C 框架使用的类型,其中可能包含 nil。将类型声明为可选(使用?
)或隐式展开(使用!
)是“安全性和便利性之间的权衡”。在本文给出的示例中,Apple 选择将类型声明为隐式解包,使调用代码更方便,但安全性较差。
也许苹果将来可能会梳理他们的框架,消除隐式解包(“可能永远不会为零”)参数的不确定性,并将它们替换为可选(“在特定情况下当然可能为零”)或标准非- 可选(“永远不会为零”)声明,基于 Objective-C 代码的确切行为。