本文系閱讀閱讀原章節後總結概括得出。由於需要我進行一定的概括提煉,如有不當之處歡迎讀者斧正。如果你對內容有任何疑問,歡迎共同交流討論。
當你十分確定可選型別不會為nil,而且你希望一旦它為nil,你的程式就崩潰時,使用!
強制解封可選型別。
以上面的flateen
方法為例:
func
flatten
(source: s)
-> [t] .map .array
}複製**
在這裡,map
方法中的$0
永遠不會是nil
,因為在前一步的操作中nil
已經被過濾掉了。此時我們完全有理由使用!
強制解封可選型別。
但這樣的例子畢竟少見,利用之前所講的各種技術,很有可能會有比直接使用強制解封更好的解決問題的辦法。在真的打算使用!
之前,還是應該回想一下是否確實沒有別的方法了。
不過有時候我們非常確定某個可選型別不是nil
,如果不幸是nil
,寧可程式直接崩潰也不繼續執行,以免導致乙個很嚴重的邏輯錯誤。在這種情況下,!
起到了乙個"解封或報錯"運算子的作用,這比使用可選鏈或用if
判斷是否為nil
更好,因為這樣不會隱藏某些理論上不可能的情況。一旦實際情況中遇到了nil
,程式崩潰,開發者就會立刻得知。
##改進強制解封的報錯資訊
我們可以提供乙個!!
運算子,它在解封可選型別的同時提供了更加詳細的報錯資訊,在程式崩潰時可以把報錯資訊列印出來:
infix
operator !! {}
-> string) -> t
複製**
現在我們就可以寫一些更加詳細的報錯資訊了,其中可以包括想要解封的值的資訊:
let s = "foo"
let i = int(s) !! "expecting integer, got \"\(s)\""
複製**
@autoclosure
確保我們只在需要的時候才使用第二個運算元。
通常情況下,我們傾向於在debug版本使用斷言然後進行一些測試。然後在實際的產品中,用乙個預設值替代nil
,比如0或者空陣列等。
我們定義乙個問嘆號運算子?!
,如果解封失敗則觸發斷言,在release版本斷言不會觸發,所以我們就提供乙個預設值:
infix
operator !? {}
-> string) -> t
複製**
於是下面這段**在debug模式下觸發斷言,在release模式下則會返回0:
let i = int(s) !? "expecting integer, got \"\(s)\""
複製**
我們可以定義乙個范型的問嘆號!?
,它可以由呼叫者手動提供預設值,這樣就不用依賴於某個具體的型別。它的引數是乙個元組,裡面有預設值和錯誤資訊:
-> (value: t, text: string)) -> t
複製**
//debug 時觸發斷言, release 時返回5
int(s) !? (5, "expected integer")
複製**
由於在可選鏈中,原來返回值為void
的方法,最終返回了void?
,我們也寫乙個非泛型的版本來檢測可選鏈在**遇到了nil
:
?, @autoclosure failuretext: () -> string)
var output: string? = nil
output?.write("something") !? "wasn't expecting chained nil here"
複製**
不管是問嘆號還是雙感嘆號,本質上都是定義了乙個雙目運算子。左側接收可選型別並且嘗試解封,右側提供相應的除錯資訊。
第四章 繼承
一 為什麼要繼承 在物件導向中我們將具有很多重複內容的類中的內容提取出來,寫成乙個單獨的類 其他類只需要繼承就能取得這些功能,同時可以在自己類中寫入獨特的自定義方法 二 繼承語法 inte ce circle nsobject 繼承是在介面中定義的 冒號後的類名是要整合的類,nsobject 是co...
第四章 物件
三個特性 身份 型別 值 每個物件都有唯一的身份來標識自己,使用內建函式id 得到。例子 usr bin env python coding utf 8 a 32 print a b a print id a id b 結果 d python27 python.exe e workp python ...
第四章 其他
sizeof和strlen 區別sizeof以位元組為單位給出資料的大小,strlen 函式以字元為單位給出字串的長度。使用strlen 函式要加 include標頭檔案。sizeof計算字元時會將標誌字串結束的不可見的空字元計算在內。定義符號常量 方法一 define name value 優點 ...