swift語言新特性:可選值
var a? 此處的a就是個可選值,意思是該值可能是缺失的.
可選
使用可選(optionals)來處理值可能缺失的情況。可選表示:
-有值,等於 x
或者
沒有值
注意:C 和 Objective-C 中並沒有可選這個概念。最接近的是 Objective-C 中的一個特性,一個方法要不返回一個物件要不返回nil,nil表示“缺少一個合法的物件”。然而,這隻對物件起作用——對於結構體,基本的 C 型別或者列舉型別不起作用。對於這些型別,Objective-C 方法一般會返回一個特殊值(比如NSNotFound)來暗示值缺失。這種方法假設方法的呼叫者知道並記得對特殊值進行判斷。然而,Swift 的可選可以讓你暗示任意型別的值缺失,並不需要一個特殊值。
來看一個例子。Swift 的String型別有一個叫做toInt的方法,作用是將一個String值轉換成一個Int值。然而,並不是所有的字串都可以轉換成一個整數。字串"123"可以被轉換成數字123,但是字串"hello, world"不行。
下面的例子使用toInt方法來嘗試將一個String轉換成Int:
- let possibleNumber = "123"
- let convertedNumber = possibleNumber.toInt()
- // convertedNumber 被推測為型別 "Int?", 或者型別 "optional Int"
因為toInt方法可能會失敗,所以它返回一個可選的(optional)Int,而不是一個Int。一個可選的Int被寫作Int?而不是Int。問號暗示包含的值是可選,也就是說可能包含Int值也可能不包含值。(不能包含其他任何值比如Bool值或者String值。只能是Int或者什麼都沒有。)
if 語句以及強制解析
你可以使用if語句來判斷一個可選是否包含值。如果可選有值,結果是true;如果沒有值,結果是false。
當你確定可選包確實含值之後,你可以在可選的名字後面加一個感嘆號(!)來獲取值。這個驚歎號表示“我知道這個可選有值,請使用它。”這被稱為可選值的強制解析(forced unwrapping):
- if convertedNumber {
- println("\(possibleNumber) has an integer value of \(convertedNumber!)")
- } else {
- println("\(possibleNumber) could not be converted to an integer")
- }
- // 輸出 "123 has an integer value of 123"
更多關於if語句的內容,請參考控制流。
注意:使用!來獲取一個不存在的可選值會導致執行時錯誤。使用!來強制解析值之前,一定要確定可選包含一個非nil的值。
可選繫結
使用可選繫結(optional binding)來判斷可選是否包含值,如果包含就把值賦給一個臨時常量或者變數。可選繫結可以用在if和while語句中來對可選的值進行判斷並把值賦給一個常量或者變數。if和while語句,請參考控制流。
像下面這樣在if語句中寫一個可選繫結:
- if let constantName = someOptional {
- statements
- }
你可以像上面這樣使用可選繫結來重寫possibleNumber這個例子:
- if let actualNumber = possibleNumber.toInt() {
- println("\(possibleNumber) has an integer value of \(actualNumber)")
- } else {
- println("\(possibleNumber) could not be converted to an integer")
- }
- // 輸出 "123 has an integer value of 123"
這段程式碼可以被理解為:
“如果possibleNumber.toInt返回的可選Int包含一個值,建立一個叫做actualNumber的新常量並將可選包含的值賦給它。”
如果轉換成功,actualNumber常量可以在if語句的第一個分支中使用。它已經被可選包含的值初始化過,所以不需要再使用!字尾來獲取它的值。在這個例子中,actualNumber只被用來輸出轉換結果。
你可以在可選繫結中使用常量和變數。如果你想在if語句的第一個分支中操作actualNumber的值,你可以改成if var actualNumber,這樣可選包含的值就會被賦給一個變數而非常量。
nil
你可以給可選變數賦值為nil來表示它沒有值:
- var serverResponseCode: Int? = 404
- // serverResponseCode 包含一個可選的 Int 值 404
- serverResponseCode = nil
- // serverResponseCode 現在不包含值
注意:nil不能用於非可選的常量和變數。如果你的程式碼中有常量或者變數需要處理值缺失的情況,請把它們宣告成對應的可選型別。
如果你宣告一個可選常量或者變數但是沒有賦值,它們會自動被設定為nil:
- var surveyAnswer: String?
- // surveyAnswer 被自動設定為 nil
注意:Swift 的nil和 Objective-C 中的nil並不一樣。在 Objective-C 中,nil是一個指向不存在物件的指標。在 Swift 中,nil不是指標——它是一個確定的值,用來表示值缺失。任何型別的可選都可以被設定為nil,不只是物件型別。
隱式解析可選
如上所述,可選暗示了常量或者變數可以“沒有值”。可選可以通過if語句來判斷是否有值,如果有值的話可以通過可選繫結來解析值。
有時候在程式架構中,第一次被賦值之後,可以確定一個可選總會有值。在這種情況下,每次都要判斷和解析可選值是非常低效的,因為可以確定它總會有值。
這種型別的可選被定義為隱式解析可選(implicitly unwrapped optionals)。把想要用作可選的型別的後面的問號(String?)改成感嘆號(String!)來宣告一個隱式解析可選。
當可選被第一次賦值之後就可以確定之後一直有值的時候,隱式解析可選非常有用。隱式解析可選主要被用在 Swift 中類的構造過程中,請參考類例項之間的迴圈強引用。
一個隱式解析可選其實就是一個普通的可選,但是可以被當做非可選來使用,並不需要每次都使用解析來獲取可選值。下面的例子展示了可選String和隱式解析可選String之間的區別:
- let possibleString: String? = "An optional string."
- println(possibleString!) // 需要驚歎號來獲取值
- // 輸出 "An optional string."
- let assumedString: String! = "An implicitly unwrapped optional string."
- println(assumedString) // 不需要感嘆號
- // 輸出 "An implicitly unwrapped optional string."
你可以把隱式解析可選當做一個可以自動解析的可選。你要做的只是宣告的時候把感嘆號放到型別的結尾,而不是每次取值的可選名字的結尾。
注意:如果你在隱式解析可選沒有值的時候嘗試取值,會觸發執行時錯誤。和你在沒有值的普通可選後面加一個驚歎號一樣。
你仍然可以把隱式解析可選當做普通可選來判斷它是否包含值:
- if assumedString {
- println(assumedString)
- }
- // 輸出 "An implicitly unwrapped optional string."
你也可以在可選繫結中使用隱式解析可選來檢查並解析它的值:
- if let definiteString = assumedString {
- println(definiteString)
- }
- // 輸出 "An implicitly unwrapped optional string."
注意:如果一個變數之後可能變成nil的話請不要使用隱式解析可選。如果你需要在變數的生命週期中判斷是否是nil的話,請使用普通可選型別。
相關文章
- 【函式式 Swift】可選值函式Swift
- C++11新特性(一):語言特性C++
- C++11新特性(三):語言特性C++
- C++11新特性(二):語言特性C++
- 現代程式語言系列2:安全表達可選值
- Swift 4.1 的新特性Swift
- [譯] Swift 5.0 新特性Swift
- 【iOS印象】Swift 4.1 新特性iOSSwift
- Swift5.0新特性更新Swift
- Swift 4.2 新特性預覽Swift
- Swift 4.1 新特性概覽Swift
- Swift 可選型別Swift型別
- Swift5 新特性預覽Swift
- Java從8到21的語言新特性Java
- C++2.0——語言新特性之Variadic TemplatesC++
- vue不支援ES2020(可選鏈)新特性配置Vue
- [swift 進階]讀書筆記-第四章:可選值 1_3 序列_魔法數問題_可選值概覽Swift筆記
- 第二章 Swift語言Swift
- Java8 新特性 —— 函數語言程式設計Java函數程式設計
- 細說 Swift 4.2 新特性:Dynamic Member LookupSwift
- OC,swift,javascript,Dart語言比較SwiftJavaScriptDart
- JavaScript 新語法 「雙問號語法」與「可選鏈語法」JavaScript
- JDK 8 新特性之函數語言程式設計 → Stream APIJDK函數程式設計API
- JDK1.8新特性值OptionalJDK
- Python 語言特性:編譯+解釋、動態型別語言、動態語言Python編譯型別
- iOS 多國語言本地化與App內語言切換(Swift)iOSAPPSwift
- Swift採用語言伺服器協議Swift伺服器協議
- ios應用開發+swift語言入門iOSSwift
- Swift 5 新特性預覽(最低支援Xcode 10.2 beta版)SwiftXCode
- Java和Go語言二選一,選擇哪門語言好?JavaGo
- Go 語言社群新提案 arena,可優化記憶體分配Go優化記憶體
- 快速瞭解C# 8.0中“可空引用型別(Nullable reference type)”語言特性C#型別Null
- “踩坑”經驗分享:Swift語言落地實踐Swift
- Swift 5新特性詳解:ABI 穩定終於來了!Swift
- Go 語言的 4 個特性改動Go
- Rust入門系列之語言特性 - 1Rust
- Chrome 71 新特性[雙語+視訊]Chrome
- C語言的角落——這些C語言不常用的特性你知道嗎?C語言
- 程式語言語法:`=`表示賦值,`:`表示型別。賦值型別