Optional chaining的秘密(二)

作為一名程序員,我們是不會(huì)甘心止步于語(yǔ)法的“甜”七芭,我們有永恒的動(dòng)力去揭開(kāi)這層語(yǔ)法的外衣一看究竟:)素挽。我們?cè)?a href="http://www.reibang.com/p/8430e8480757" target="_blank">《Optional chaining的秘密(一)》中指出了,在類(lèi)型的后面使用?表示Optional類(lèi)型狸驳,而?.則是map 方法的語(yǔ)法糖预明。

我們今天要研究的是在類(lèi)型的后面使用!意味著什么?

ImplicitlyUnwrappedOptional

只要我們隨便翻翻官方文檔,我們就能知道耙箍,下面這段代碼是編譯不過(guò)的

let x: String? = "Hello,world"
func printString(str: String) {
    print(str)
}
printString(x) // error!!!!!!

原因就在于 xString撰糠? 聲明為一個(gè)Optional<String>類(lèi)型了,而方法printString()要求的參數(shù)是 String 類(lèi)型辩昆,所以如果直接傳遞 x 會(huì)導(dǎo)致調(diào)用失敗阅酪,如果我們希望方法調(diào)用成功,那么我們需要這樣處理汁针。

printString(x!)

我們需要使用 ! 強(qiáng)制對(duì) x 進(jìn)行拆封术辐,使其還原為 String 類(lèi)型。那么如果 ! 放在類(lèi)型的后面意味著什么呢扇丛?

let x: String! = "Hello,world"
func printString(str: String) {
    print(str)
}
printString(x) // ok!!!!!!

文檔把這種 let x: String! 稱(chēng)為隱式拆封(implicitly unwrapped),在 implicitly unwrapped 的幫助下术吗,我們可以看到printString(x)中的參數(shù)x不需要強(qiáng)制拆封了。難道let x: String!為我們定義了一個(gè)String類(lèi)型帆精?no,no,no,no

我們?cè)诳匆粋€(gè)長(zhǎng)一點(diǎn)的例子。

public class Demo {
    public var subDemo: SubDemo! = nil
}

public class SubDemo {
    public let count: Int = 1
}

let demo: Demo! = Demo()
demo.subDemo = SubDemo()

let count = demo.subDemo.count

在這個(gè)代碼片段中,我們有兩處值得注意:

  • public var subDemo: SubDemo! = nil可以被聲明為nil
  • let count = demo.subDemo.count 可以chaining式調(diào)用

第一點(diǎn)是比較容易解釋的卓练,subDemo之所以可以被聲明為nil是因?yàn)椋?code>SubDemo!聲明了一個(gè)ImplicitlyUnwrappedOptional類(lèi)型隘蝎,也就是說(shuō)它不是一個(gè)普通的類(lèi)型,如果它是一個(gè)普通的SubDemo類(lèi)型襟企,那么它一定不允許為nil.

如何完成鏈?zhǔn)降恼{(diào)用

那怎么解釋第二點(diǎn)嘱么,鏈?zhǔn)秸{(diào)用呢?讓我們循序漸進(jìn),我們現(xiàn)在有這樣個(gè)方法顽悼,可以給一個(gè)string做擴(kuò)展

extension String {
    static func appendingString(str: String) -> (String) -> String {
        return { str + $0 }
    }
}

var aStr = "Hello"
var bString = String.appendingString(aStr)("!")
var method = String.appendingString(aStr)
var cStr = method("!")

現(xiàn)在我們定義個(gè)操作符方法:+- 它可以幫助我們實(shí)現(xiàn)上面同樣的功能

infix operator +- { associativity left }
func +-<T,Z>(obj:T, f:T->Z) -> Z {
    return f(obj)
}

通過(guò)這個(gè)中綴操作符的定義曼振,我們可以這樣實(shí)現(xiàn)給一個(gè)字符做擴(kuò)展的功能。

let helloString = "hello" +- {
    String.appendingString($0)("!")
}

操作符 +- 接收兩個(gè)參數(shù)蔚龙,一個(gè)是字符串"hello",另外一個(gè)是閉包冰评。而且通過(guò)associativity的聲明,這種操作可以還可以產(chǎn)生一個(gè)連綴式調(diào)用木羹。

let helloString = "hello" +- {
    String.appendingString($0)("!")
    } +- { String.appendingString($0)("!") }

說(shuō)了這么多甲雅,不知道我們又沒(méi)有注意,我們現(xiàn)在已經(jīng)可以對(duì) String 類(lèi)型做類(lèi)似 ?. 操作了坑填,只是當(dāng)前類(lèi)型是String,我們現(xiàn)在要將其適用于ImplicitlyUnwrappedOptional類(lèi)型抛人。

infix operator +- { associativity left  }
func +-<T,Z>(obj:ImplicitlyUnwrappedOptional<T>, f:T->Z) -> ImplicitlyUnwrappedOptional<Z> {
    switch obj {
    case .Some(let x):
        return f(x)
    case .None:
        fatalError()
    }
}

我們重新實(shí)現(xiàn)操作符 +- 的定義,使其接收一個(gè)ImplicitlyUnwrappedOptional類(lèi)型的參數(shù)并返回一個(gè)ImplicitlyUnwrappedOptional類(lèi)型的值脐瑰。方法體內(nèi)容會(huì)對(duì)參數(shù)obj進(jìn)行拆包妖枚,如果為nil則會(huì)報(bào)錯(cuò),否則經(jīng)過(guò)轉(zhuǎn)換后返回ImplicitlyUnwrappedOptional苍在,這不就是完整的implicitly unwrapped的工作過(guò)程嗎绝页?好,現(xiàn)在我們把String聲明為implicitly unwrapped

var oldString: String! = "hello"  // String!

let helloString = oldString +- {
    String.appendingString($0)("!")
    } +- { String.appendingString($0)("!") }

這就是Optinal chainingimplicitly unwrapped 是的工作過(guò)程忌穿。

總結(jié)

以上代碼在xcode 7.3上都測(cè)試通過(guò)抒寂。雖然代碼沒(méi)有swift的鏈?zhǔn)讲僮鞣a那樣漂亮,但這些功能確實(shí)可以通過(guò)純swift代碼來(lái)實(shí)現(xiàn)掠剑。希望這些內(nèi)容有助于大家對(duì)optional更深入的理解屈芜。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市朴译,隨后出現(xiàn)的幾起案子井佑,更是在濱河造成了極大的恐慌,老刑警劉巖眠寿,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件躬翁,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡盯拱,警方通過(guò)查閱死者的電腦和手機(jī)盒发,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)例嘱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人宁舰,你說(shuō)我怎么就攤上這事拼卵。” “怎么了蛮艰?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵腋腮,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我壤蚜,道長(zhǎng)即寡,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任袜刷,我火速辦了婚禮聪富,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘水泉。我一直安慰自己善涨,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布草则。 她就那樣靜靜地躺著钢拧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪炕横。 梳的紋絲不亂的頭發(fā)上源内,一...
    開(kāi)封第一講書(shū)人閱讀 51,125評(píng)論 1 297
  • 那天,我揣著相機(jī)與錄音份殿,去河邊找鬼膜钓。 笑死,一個(gè)胖子當(dāng)著我的面吹牛卿嘲,可吹牛的內(nèi)容都是我干的颂斜。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼拾枣,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼沃疮!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起梅肤,我...
    開(kāi)封第一講書(shū)人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤司蔬,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后姨蝴,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體俊啼,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年左医,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了授帕。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片同木。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖豪墅,靈堂內(nèi)的尸體忽然破棺而出泉手,到底是詐尸還是另有隱情黔寇,我是刑警寧澤偶器,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站缝裤,受9級(jí)特大地震影響屏轰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜憋飞,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一霎苗、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧榛做,春花似錦唁盏、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至锰瘸,卻和暖如春刽严,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背避凝。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工舞萄, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人管削。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓倒脓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親含思。 傳聞我的和親對(duì)象是個(gè)殘疾皇子崎弃,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • 基礎(chǔ)部分(The Basics) 當(dāng)推斷浮點(diǎn)數(shù)的類(lèi)型時(shí),Swift 總是會(huì)選擇Double而不是Float茸俭。 結(jié)合...
    gamper閱讀 1,286評(píng)論 0 7
  • 對(duì)各種值為"空"的情況處理不當(dāng)吊履,幾乎是所有Bug的來(lái)源。 在我們的例子里调鬓,盡管tmp的值是nil艇炎,但調(diào)用tmp的r...
    AKyS佐毅閱讀 10,515評(píng)論 1 13
  • Swift 是一門(mén)開(kāi)發(fā) iOS, macOS, watchOS 和 tvOS 應(yīng)用的新語(yǔ)言。然而腾窝,如果你有 C 或...
    XLsn0w閱讀 922評(píng)論 2 1
  • 聊聊費(fèi)蘭克的寫(xiě)作訓(xùn)練營(yíng) 近來(lái)喜歡上了寫(xiě)作缀踪,而且想提高一下寫(xiě)作水平居砖,又偶然知道了一個(gè)叫做費(fèi)蘭克的家伙花了十多萬(wàn)去學(xué)習(xí)...
    簡(jiǎn)單國(guó)平閱讀 427評(píng)論 2 49
  • 江梅從一片混沌中醒來(lái)的時(shí)候,厚重的遮光窗簾嚴(yán)實(shí)地?fù)踝×舜巴獾木跋舐客蓿虼怂矡o(wú)法辨認(rèn)此刻到底是白晝還是黑夜奏候。 黑暗中...
    _云本_閱讀 244評(píng)論 0 1