第四章 何時使用強制解封

2021-09-11 10:11:05 字數 2184 閱讀 3040

本文系閱讀閱讀原章節後總結概括得出。由於需要我進行一定的概括提煉,如有不當之處歡迎讀者斧正。如果你對內容有任何疑問,歡迎共同交流討論。

當你十分確定可選型別不會為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 優點 ...