在物件導向程式語言中,如果一開始沒有定義一個變數本身儲存的資料,通常會用 nil(null) 來先定義變數,然後在後面要使用到這個變數時,進行物件的初始化。
在沒有 Optional 的狀況下,程式必須要在使用該變數時,先檢查這個變數倒底初始化了沒,如果沒有初始化,還得跳過使用這個變數的程式區塊,或是直接在這裡初始化,古早以前的 Java 程式就常常遇到這樣的問題,在使用到沒有初始化的變數時,發生 Null Pointer Exception,而造成程式 crash。
Optional 的宣告
swift 的 Optional 是以 enum 的方式實作,Optional 所代表的意義為 "there is a value, and it equals x" 或是 "there isn’t a value at all"
Optional 的定義宣告如下,可得知有兩種case: 有值 Some 及 無值 None
public enum Optional<Wrapped> : _Reflectable, NilLiteralConvertible {
case None
case Some(Wrapped)
}
Optional 就像是一個物件的包裝盒/包裹,裡面裝了 Some 或是 None 兩種東西,Some 就是盒子裡裝了其他類型的物件 instance,None 就是盒子裡面沒有東西。
在 swift 要可以用 Optional.some 或是 Optional.none 包裝物件 instance。
let box = Optional.some("iphone")
let box2:Optional<String> = Optional.some("iphone")
let box3:Optional<String> = Optional.none
print("box3 is \(box3)")
? 是 swift 裡面針對 Optioanl 的 syntax sugar,在宣告時,型別後面加上?,就可以宣告該變數為 Optional
var newbox:String?
newbox = nil
print("newbox is \(newbox)")
let newbox2:String? = "iphone"
let newbox3:String? = nil
使用 Optional 裡面的物件
Optional 是個包裝盒,要使用 optional 變數必須要用下面幾種方式,將盒子拆開
- 使用 !
要使用 Optional 可用下面 unwrap 函數取得裡面的物件,但在 box 為 nil 時,會發生 crash 的狀況
func unwrap<String>(box:Optional<String>) -> String {
switch box {
case .none:
fatalError("it is Nil !!!")
case let .some(boxval):
return boxval
}
}
let tempbox1 = unwrap(box: "iphone")
//let tempbox2 = unwrap(box: nil)
在 swift 可用 ! 這個 syntax sugar 語法,其功能就跟 unwrap 一樣,遇到 nil 時,程式會 crash。
let tempbox3 = newbox2!
//let tempbox4 = newbox3!
- if
先用 if 判斷一下 Optional 裡面有沒有東西,如果有就打開使用,如果沒有就不處理
if newbox2 != nil {
print ("newbox2 is \(newbox2!)")
}
if newbox3 != nil {
print ("newbox3 is \(newbox3!)")
}
- if let
可簡化第二種方式的實作,直接將盒子裡的物件指定給另一個變數
if let pbox2 = newbox2 {
print("pbox2 is = \(newbox2!)")
} else {
print("pbox2 is nil")
}
if let pbox3 = newbox3 {
print("pbox3 is = \(newbox3!)")
} else {
print("pbox3 is nil")
}
- Assigned Value if nil
用另一個變數來儲存物件 instance,但在打開 Optional 時,如果發現是 nil,就將新的變數初始化為空白的字串
let pbox5: String
if let pbox4 = newbox2 {
pbox5 = pbox4
} else {
pbox5 = ""
}
Optional Chaining ?.
Optioanl Chaining ?. 是 swift 的另一個 syntax sugar
[object]?.[property]?.[property | method]?.[method]
class Person {
var residence: Residence?
}
class Residence {
var numberOfRooms = 1
}
直接用 ! 打開 john 時,會造成程式 crash,但改用 ?.,可避免這樣的問題。
let john = Person()
//let roomCount = john.residence!.numberOfRooms
let roomCount = john.residence?.numberOfRooms
使用 ?. 可在打開 optional 時,進行 nil 的檢查及保護,搭配 if let 使用,就可以避免因為 nil 而造成程式 crash。
if let roomCount2 = john.residence?.numberOfRooms {
print("John's residence has \(roomCount2) room(s).")
} else {
print("Unable to retrieve the number of rooms.")
}
john.residence = Residence()
if let roomCount3 = john.residence?.numberOfRooms {
print("John's residence has \(roomCount3) room(s).")
} else {
print("Unable to retrieve the number of rooms.")
}
沒有留言:
張貼留言