Swift语言中的感叹号是什么意思?

本文翻译自:What does an exclamation mark mean in the Swift language?

The Swift Programming Language guide has the following example: 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

I'm very new to the Swift language. 我对Swift语言很新。 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?

that does NOT mean that " john is of type Person and it might be nil", as I originally thought. 这并不意味着“ john属于Person ,它可能是零”,正如我原先想的那样。 I was simply misunderstanding that Person and Person? 我只是误认为PersonPerson? are completely separate types. 是完全独立的类型。 Once I grasped that, all of the other ? 一旦我掌握了这一切,所有其他人? , ! ! madness, and the great answers below, made a lot more sense. 疯狂,以及下面的好答案,更有意义。


#1楼

参考:https://stackoom.com/question/1cmGN/Swift语言中的感叹号是什么意思


#2楼

john is an optional var . john是一个可选的var So can be contains a nil value. 所以可以包含nil值。 To ensure that the value isn't nil use a ! 确保价值不是零使用! at the end of the var name. var名称的末尾。

From documentation 从文档

“Once you're sure that the optional does contain a value, you can access its underlying value by adding an exclamation mark (!) to the end of the optional's name. “一旦确定可选项包含值,就可以通过在可选项名称的末尾添加感叹号(!)来访问其基础值。 The exclamation mark effectively says, “I know that this optional definitely has a value; 感叹号有效地说:“我知道这个选项肯定有价值; please use it.” 请用它。“

Another way to check non nil value is 另一种检查非零值的方法是

    if let j = json {
        // do something with j
    }

#3楼

John is an optional Person, meaning it can hold a value or be nil. John是一个可选的Person,意思是它可以保持一个值或为零。

john.apartment = number73

is used if john is not an optional. 如果john不是可选的,则使用。 Since john is never nil we can be sure it won't call apartment on a nil value. 由于约翰永远不会是零,我们可以肯定它不会以零值称公寓。 While

john!.apartment = number73

promises the compiler that john is not nil then unwraps the optional to get john's value and accesses john's apartment property. 承诺编译器john不是nil然后解包可选来获取john的值并访问john的公寓属性。 Use this if you know that john is not nil. 如果你知道约翰不是零,请使用此选项。 If you call this on a nil optional, you'll get a runtime error. 如果你在一个nil可选项上调用它,你将收到运行时错误。

The documentation includes a nice example for using this where convertedNumber is an optional. 该文档包含一个很好的例子,用于使用convertNumber是可选的。

if convertedNumber {
    println("\(possibleNumber) has an integer value of \(convertedNumber!)")
} else {
    println("\(possibleNumber) could not be converted to an integer")
}

#4楼

If john were an optional var (declared thusly) 如果john是一个可选的var(由此声明)

var john: Person?

then it would be possible for john to have no value (in ObjC parlance, nil value) 那么约翰就有可能没有价值(用ObjC的说法,零价值)

The exclamation point basically tells the compiler "I know this has a value, you don't need to test for it". 感叹号基本上告诉编译器“我知道它有一个值,你不需要测试它”。 If you didn't want to use it, you could conditionally test for it: 如果您不想使用它,您可以有条件地测试它:

if let otherPerson = john {
    otherPerson.apartment = number73
}

The interior of this will only evaluate if john has a value. 这个内部只会评估john是否有值。


#5楼

What does it mean to "unwrap the instance"? “打开实例”是什么意思? Why is it necessary? 为什么有必要?

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 . 术语“包裹”意味着我们应该将一个可选变量视为礼物,用闪亮的纸包裹,可能(可悲的是)是空的

When "wrapped", the value of an Optional variable is an enum with two possible values (a little like a Boolean). 当“换行”时,Optional变量的值是一个带有两个可能值的枚举(有点像布尔值)。 This enum describes whether the variable holds a value ( Some(T) ), or not ( None ). 此枚举描述变量是否包含值( Some(T) )或不包含( None )。

If there is a value, this can be obtained by "unwrapping" the variable (obtaining the T from Some(T) ). 如果有值,可以通过“展开”变量(从Some(T)获得T来获得。

How is john!.apartment = number73 different from john.apartment = number73 ? john!.apartment = number73john.apartment = number73什么不同? (Paraphrased) (意译)

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). 如果你写了一个Optional变量的名字(例如文本john ,没有! ),这就是“包装”枚举(Some / None),而不是值本身(T)。 So john isn't an instance of Person , and it doesn't have an apartment member: 所以john不是Person的实例,它没有apartment成员:

john.apartment
// 'Person?' does not have a member named 'apartment'

The actual Person value can be unwrapped in various ways: 实际的Person值可以通过各种方式解包:

  • "forced unwrapping": john! “强行打开”: john! (gives the Person value if it exists, runtime error if it is nil) (如果存在,则给出Person值,如果为零则给出运行时错误)
  • "optional binding": if let p = john { println(p) } (executes the println if the value exists) “可选绑定”: if let p = john { println(p) } (如果值存在则执行println
  • "optional chaining": john?.learnAboutSwift() (executes this made-up method if the value exists) “可选链接”: john?.learnAboutSwift() (如果值存在,则执行此john?.learnAboutSwift()方法)

I guess you choose one of these ways to unwrap, depending upon what should happen in the nil case, and how likely that is. 我想你会选择其中一种解包方式,具体取决于nil情况应该发生什么,以及它有多大可能。 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). 这种语言设计强制明确处理nil case,我想这可以提高Obj-C的安全性(很容易忘记处理nil的情况)。

Update : 更新

The exclamation mark is also used in the syntax for declaring "Implicitly Unwrapped Optionals". 感叹号也用于声明“Implicitly Unwrapped Optionals”的语法中。

In the examples so far, the john variable has been declared as var john:Person? 在到目前为止的示例中, john变量已声明为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. 如果您想要该变量的实际值,则必须使用上述三种方法之一将其展开。

If it were declared as var john:Person! 如果它被声明为var john:Person! instead, the variable would be an Implicitly Unwrapped Optional (see the section with this heading in Apple's book). 相反,该变量将是一个Implicitly Unwrapped Optional(请参阅Apple的书中带有此标题的部分)。 There is no need to unwrap this kind of variable when accessing the value, and john can be used without additional syntax. 访问该值时无需解包这种变量,并且可以在没有其他语法的情况下使用john But Apple's book says: 但苹果公司的书说:

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. 如果需要在变量的生命周期内检查nil值,请始终使用普通的可选类型。

Update 2 : 更新2

The article " Interesting Swift Features " by Mike Ash gives some motivation for optional types. Mike Ash的文章“ 有趣的快速特征 ”为可选类型提供了一些动力。 I think it is great, clear writing. 我认为这很棒,写得很清楚。

Update 3 : 更新3

Another useful article about the implicitly unwrapped optional use for the exclamation mark: " Swift and the Last Mile " by Chris Adamson. 另一篇关于感叹号隐式解包的可选用法的文章:Chris Adamson的“ Swift and the Last Mile ”。 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. 文章解释说,这是Apple用来声明其Objective-C框架使用的类型的实用指标,这些框架可能包含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选择将类型声明为隐式展开,使调用代码更方便,但安全性更低。

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. 也许苹果可能在未来梳理他们的框架,消除隐含地解开(“可能永远不会”)参数的不确定性,并用可选的替换它们(“肯定可能是零[希望,有记录!]情况”)或标准非-optional(“永远不会是”)声明,基于其Objective-C代码的确切行为。


#6楼

In objective C variables with no value were equal to 'nil'(it was also possible to use 'nil' values same as 0 and false), hence it was possible to use variables in conditional statements (Variables having values are same as 'TRUE' and those with no values were equal to 'FALSE'). 在目标C中,没有值的变量等于'nil'(也可以使用与0和false相同的'nil'值),因此可以在条件语句中使用变量(具有值的变量与'TRUE相同'和那些没有价值观的人等于'假')。

Swift provides type safety by providing 'optional value'. Swift通过提供“可选值”来提供类型安全性。 ie It prevents errors formed from assigning variables of different types. 即它可以防止因分配不同类型的变量而形成的错误。

So in Swift, only booleans can be provided on conditional statements. 所以在Swift中,只能在条件语句中提供布尔值。

var hw = "Hello World"

Here, even-though 'hw' is a string, it can't be used in an if statement like in objective C. 在这里,偶数'虽然'hw'是一个字符串,但它不能在if语句中使用,就像在Objective C中一样。

//This is an error

if hw

 {..}

For that it needs to be created as, 为此,它需要创建为,

var nhw : String? = "Hello World"

//This is correct

if nhw

 {..}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值