2017年1月26日 星期四

Swift 3 學習:可選型別 (Optionals)


可選型別(Optionals)


  Swift 有一個特別的型別:可選型別(Optionals),宣告成可選型別的變數,代表此變數要嘛有值,要嘛什麼值都沒有(nil)。宣告方法為在型別後面加上?號,例如:整數可選型別為 Int?, 浮點數可選型別為 Double?

  例如,要將字串型別轉換成整數型別的話,因為不是所有字串都可以轉換成整數,所以這樣子轉換出來的值,須用整數可選型別來表示:
let possibleNumber = "123"
var convertedNumber = Int(possibleNumber)
此時 convertedNumber 的型別會被自動判別為可選整數型別 Int?,其值為整數的 123。而如果是無法轉成整數的字串:
let impossibleNumber = "Hello"
var convertedNumber = Int(impossibleNumber)
此時 convertedNumber 的型別會被自動判別為可選整數型別 Int?,其值為 nil,代表它什麼值都沒有。


  可選型別變數在宣告時,若沒有給予初始值,編譯器會自動給予 nil 值。以下二種寫法,效果相同:
  •  var convertedNumber: Int? = nil
  •  var convertedNumber: Int?
只有可選型別可以指定其值為 nil,一般型別不可。可選型別變數的值不是 nil 的話,必須在變數後面加上驚嘆號(!)來取值才可以進行運算,但若是可選型別是 nil 時,就不能加上驚嘆號(!),否則會發生錯誤。
var convertedNumber = Int("123")var newNumber: Intif convertedNumber != nil {   newNumber = convertedNumber! }else{   print("convertedNumber has no value, set default to zero")   newNumber = 0 }
由上面的程式碼可看出可選型別加上驚嘆號(!)來取值後,回傳的型別是一般型別,所以可以用來指派值給一般型別的 newNumber,但是當可選型別為 nil 時 ,必須另外指定預設值,這樣的寫法有點冗長,Swift 提供了 "??" 運算子來簡化這類的程式碼,用法是 ( Optionals ?? defaultValue ),意思是:當可選型別 Optionals 有值時,返回加上驚嘆號取值後的值,而當 Optionals 為 nil 時,返回預設值 defaultValue:
var convertedNumber = Int("123")var newNumber = convertedNumber ?? 0


可選型別的綁定 (Optional Binding)


  如果常數或變數 x 的宣告是在 ifwhile 的條件判斷裡面,而且被給予一個可選型別 b 做初始化,當 b 不是 nil 時,這個常數或變數 x 的範圍將會被綁定在可選型別 b 除了 nil 以外的所有值內,也就是說 x 等同於一般的常數或變數,而 x 可運作範圍也會被綁定在條件為真時的運作括號{}內,當 b nil 時,則執行條件為假時的內容。這種方法稱為可選型別的綁定(Optional Binding)。
var a:String = "Hello "
var b:String? = "World"

if let x = b {    // The type of x is String, not String?
    print(a+x)
}else{
    // cannot operate x here    print("b is nil")}

可選鏈(Optional chaining)


  要對可選型別變數做點運算時,如果可選型別的值不是 nil 時,可以在可選型別變數後面加上驚嘆號(!)來做點運算,此時回傳的型別會是一般型別,而當變數值是 nil 時,用驚嘆號(!)來取值則會發生錯誤。要避免這樣的問題發生,可以改成在變數後面加上問號(?)來做點運算,此時回傳的型別會是可選型別,當變數值是 nil 時,用問號(?)做點運算會回傳 nil,不會造成錯誤。這種問號加上點運算(?.)的用法,稱為可選鏈(Optional chaining)。因為可選鏈回傳的型別也是可選型別,所以回傳後的可選型別也一樣可以使用可選鏈及可選型別的綁定語法。使用可選鏈的好處是:在一連串的可選鏈點運算中,只要有一個可選型別的值是 nil,最終結果就會回傳 nil,這樣可以少掉許多判斷式。
var str1:String? = "Hello "
// str1 不是 nil,可以使用"!"取值做點運算,此時 str2 的型別會判定為 String
var str2 = str1!.appending("World")
// str1 也可以使用"?"做點運算,此時 str3 的型別會判定為 String?var str3 = str1?.appending("World")
// str1 如果是 nil 的話,只能使用"?"做點運算,此時 str4 的值為 nilstr1 = nilvar str4 = str1?.appending("World"


隱式解析可選型別 (Implicitly Unwrapped Optionals)


  可選型別每次取值時,都須使用"!"來取值,如果有些時候可選型別只有一開始預設值是 nil,之後給予值後就會一直有值而不會變成 nil,這樣我們可以在宣告這種可選型別時,用驚嘆號(!)來取代問號(?),這樣這種可選型別在使用時就可以自動取值而不必加上"!"。
var myName: String! = "AppCoolbao"
print("Hello \(myName)")

沒有留言:

張貼留言