问题描述
Swift 编程语言指南下面的例子:
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/content/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html)
然后在将公寓分配给此人时,他们使用感叹号来打开实例":
Then when assigning the apartment to the person, they use an exclamation point to "unwrap the instance":
john!.apartment = number73
打开实例"是什么意思?为什么有必要?它与仅执行以下操作有何不同:
What does it mean to "unwrap the instance"? Why is it necessary? How is it different from just doing the following:
john.apartment = number73
我对 Swift 语言非常陌生.只是想了解基础知识.
I'm very new to the Swift language. Just trying to get the basics down.
更新:
我遗漏的最大难题(没有直接在答案中说明 - 至少在撰写本文时没有说明)是当您执行以下操作时:
UPDATE:
The big piece of the puzzle that I was missing (not directly stated in the answers - at least not at the time of writing this) is that when you do the following:
var john: Person?
这并不意味着john
是 Person
类型并且它可能是 nil",正如我最初的想法.我只是误解了 Person
和 Person?
是完全不同的类型.一旦我掌握了这一点,所有其他 ?
、!
的疯狂以及下面的精彩答案都会变得更有意义.
that does NOT mean that "john
is of type Person
and it might be nil", as I originally thought. I was simply misunderstanding that Person
and Person?
are completely separate types. Once I grasped that, all of the other ?
, !
madness, and the great answers below, made a lot more sense.
推荐答案
据我所知(这对我来说也很新)...
As far as I can work out (this is very new to me, too)...
术语包装"意味着我们应该将可选变量视为礼物,包裹在闪亮的纸中,可能(可悲的是!)是空的.
The term "wrapped" implies we should think of an Optional variable as a present, wrapped in shiny paper, which might (sadly!) be empty.
当包装"时,Optional 变量的值是一个具有两个可能值的枚举(有点像布尔值).这个枚举描述了变量是否持有一个值(Some(T)
),或者没有(None
).
When "wrapped", the value of an Optional variable is an enum with two possible values (a little like a Boolean). This enum describes whether the variable holds a value (Some(T)
), or not (None
).
如果有值,可以通过解包"变量来获得(从Some(T)
中获得T
).
If there is a value, this can be obtained by "unwrapping" the variable (obtaining the T
from Some(T)
).
john!.apartment = number73
与 john.apartment = number73
有何不同?(转述)
如果你写了一个可选变量的名字(例如文本john
,没有!
),这指的是包装"的枚举(Some/None),不是值本身 (T).所以 john
不是 Person
的实例,它没有 apartment
成员:
If you write the name of an Optional variable (eg text john
, without the !
), this refers to the "wrapped" enum (Some/None), not the value itself (T). So john
isn't an instance of Person
, and it doesn't have an apartment
member:
john.apartment
// 'Person?' does not have a member named 'apartment'
实际的 Person
值可以通过多种方式展开:
The actual Person
value can be unwrapped in various ways:
- "forced unwrapping":
john!
(如果存在则给出Person
值,如果为nil则给出运行时错误) - 可选绑定":
if let p = john { println(p) }
(如果值存在则执行println
) - 可选链":
john?.learnAboutSwift()
(如果值存在,则执行这个编造的方法)
- "forced unwrapping":
john!
(gives thePerson
value if it exists, runtime error if it is nil) - "optional binding":
if let p = john { println(p) }
(executes theprintln
if the value exists) - "optional chaining":
john?.learnAboutSwift()
(executes this made-up method if the value exists)
我猜你会选择这些方法中的一种来解包,这取决于在 nil 情况下会发生什么,以及发生的可能性.这种语言设计强制显式处理 nil 情况,我认为这比 Obj-C 提高了安全性(很容易忘记处理 nil 情况).
I guess you choose one of these ways to unwrap, depending upon what should happen in the nil case, and how likely that is. This language design forces the nil case to be handled explicitly, which I suppose improves safety over Obj-C (where it is easy to forget to handle the nil case).
更新:
感叹号也用于声明隐式解包的可选项"的语法中.
The exclamation mark is also used in the syntax for declaring "Implicitly Unwrapped Optionals".
在到目前为止的示例中,john
变量已声明为 var john:Person?
,并且它是一个 Optional.如果您想要该变量的实际值,则必须使用上述三种方法之一对其进行解包.
In the examples so far, the john
variable has been declared as var john:Person?
, and it is an Optional. If you want the actual value of that variable, you must unwrap it, using one of the three methods above.
如果它被声明为 var john:Person!
而不是,该变量将是一个隐式解包可选(请参阅 Apple 书中带有此标题的部分).访问值时不需要解包这种变量,并且可以使用 john
而无需额外的语法.但苹果的书说:
If it were declared as var john:Person!
instead, the variable would be an Implicitly Unwrapped Optional (see the section with this heading in Apple's book). There is no need to unwrap this kind of variable when accessing the value, and john
can be used without additional syntax. But Apple's book says:
当变量有可能在以后变为 nil 时,不应使用隐式解包的可选项.如果您需要在变量的生命周期内检查 nil 值,请始终使用普通的可选类型.
更新 2:
迈克的文章有趣的 Swift 功能"Ash 为可选类型提供了一些动力.我认为它很棒,文字清晰.
The article "Interesting Swift Features" by Mike Ash gives some motivation for optional types. I think it is great, clear writing.
更新 3:
另一篇关于隐式解包可选用于感叹号的有用文章:斯威夫特和最后一英里",克里斯·亚当森 (Chris Adamson).文章解释说,这是 Apple 用于声明其 Objective-C 框架使用的可能包含 nil 的类型的实用措施.将类型声明为可选(使用 ?
)或隐式解包(使用 !
)是安全性和便利性之间的权衡".在文章中给出的示例中,Apple 选择将类型声明为隐式解包,使调用代码更方便,但安全性较低.
Another useful article about the implicitly unwrapped optional use for the exclamation mark: "Swift and the Last Mile" by Chris Adamson. The article explains that this is a pragmatic measure by Apple used to declare the types used by their Objective-C frameworks which might contain nil. Declaring a type as optional (using ?
) or implicitly unwrapped (using !
) is "a tradeoff between safety and convenience". In the examples given in the article, Apple have chosen to declare the types as implicitly unwrapped, making the calling code more convenient, but less safe.
也许 Apple 可能会在未来梳理他们的框架,消除隐式解包(可能永远不会为零")参数的不确定性,并用可选参数替换它们(特别是 [希望,记录在案!] 情况下,当然可能为零")或标准的非可选(永远不会为零")声明,基于其 Objective-C 代码的确切行为.
Perhaps Apple might comb through their frameworks in the future, removing the uncertainty of implicitly unwrapped ("probably never nil") parameters and replacing them with optional ("certainly could be nil in particular [hopefully, documented!] circumstances") or standard non-optional ("is never nil") declarations, based on the exact behaviour of their Objective-C code.
这篇关于感叹号在 Swift 语言中是什么意思?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!