class Person { let name: String init(name: String) { self.name = name } var apartment: Apartment? deinit { println("\(name) is being deinitialized") } } class Apartment { let number: Int init(number: Int) { self.number = number } var tenant: Person? deinit { println("Apartment #\(number) is being deinitialized") } } var john: Person? var number73: Apartment? john = Person(name: "John Appleseed") number73 = Apartment(number: 73) //From Apple's “The Swift Programming Language” guide (https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html)
然后当将公寓分配给人时,他们使用感叹号来“解开实例”:
john!.apartment = number73
“解包实例”是什么意思?为什么有必要?它与仅执行以下操作有什么不同:
john.apartment = number73
我对Swift语言很新。只是试图让基础下来。
更新:
我缺少的那块拼图的大块(在答案中没有直接说明 – 至少在写这篇文章的时候)是,当你做以下事情时:
var john: Person?
这并不意味着“john的类型是Person,它可能是nil”,正如我原来想的。我只是误会了人和人?是完全独立的类型。一旦我掌握了,所有的其他?,!疯狂,和下面的伟大的答案,做了很多更有意义。
What does it mean to “unwrap the instance”? Why is it necessary?
就我可以工作(这对我来说也是新的)…
术语“包裹”意味着我们应该将一个可选变量看作一个礼物,包裹在闪亮的纸上,这可能(可悲的是)是空的。
当“包装”时,可选变量的值是具有两个可能值的枚举(有点像布尔值)。此枚举描述变量是否保存一个值(Some(T))或不保存(None)。
如果有一个值,这可以通过“展开”变量(从一些(T)获得T)获得。
How is
john!.apartment = number73
different fromjohn.apartment = number73
? (Paraphrased)
如果你写一个可选变量的名字(例如text john,没有!),这指的是“包装”枚举(Some / None),而不是值本身(T)。所以john不是Person的实例,它没有公寓成员:
john.apartment // 'Person?' does not have a member named 'apartment'
实际的Person值可以通过多种方式展开:
>“强制解包”:john! (给出Person值,如果存在,运行时错误,如果它是nil)
>“可选绑定”:如果let p = john {println(p)}(如果值存在,则执行println)
>“可选链接”:john?.learnAboutSwift()(如果值存在,则执行此修改方法)
我想你选择这些方式之一解开,这取决于在nil情况下应该发生什么,这是多大可能。这种语言设计强制要明确处理nil情况,我认为提高安全性比Obj-C(其中很容易忘记处理nil情况)。
更新:
感叹号也用于声明“隐式已解包可选”的语法。
在到目前为止的示例中,john变量已声明为var john:Person ?,它是一个可选。如果你想要该变量的实际值,你必须使用上面三种方法之一来解开它。
如果它被声明为var john:Person!相反,变量将是一个隐式解包可选(参见苹果公司书中的这一标题部分)。在访问该值时,不需要解开这种类型的变量,并且可以在没有其他语法的情况下使用john。但是苹果的书说:
Implicitly unwrapped optionals should not be used when there is a possibility of a variable becoming nil at a later point. Always use a normal optional type if you need to check for a nil value during the lifetime of a variable.
更新2:
Mike Ash的文章“Interesting Swift Features”给出了可选类型的一些动机。我认为这是伟大的,清晰的写作。
更新3:
关于感叹号的隐式解包可选使用的另一篇有用的文章:“Swift and the Last Mile”by Chris Adamson。文章解释说,这是一个务实的措施,由苹果用来声明的Objective-C框架使用的类型,可能包含nil。将类型声明为可选(使用?)或隐式解包(使用!)是“安全和方便之间的权衡”。在本文中给出的示例中,Apple已经选择将类型声明为隐式解包,使调用代码更方便,但不太安全。
也许苹果可能梳理他们的框架在未来,消除隐含的解开(“可能永远不是”)参数的不确定性,并用可选的替换它们(“肯定可能是零的特定[希望,记录!]情境”)或标准非-optional(“永远不是nil”)声明,基于其Objective-C代码的确切行为。