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

 {..}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章