iOS9 with Swift 擴展

擴展:

擴展是將你自己的代碼插入到已經(jīng)存在的對象類型中的方法埃唯,即extending an existing object type。這種擴展可以在自己定義的類型中停局,也可以是Swift本身的對象類型岛抄,還可以是Cocoa的對象類型』】桑總之,擴展可以將你的代碼打入你的甚至別人的類型中文虏!

擴展的聲明必須是在文件的最頂端侣诺。聲明擴展:關(guān)鍵字extension放在已經(jīng)存在的對象類型名之前殖演,之后如果要加協(xié)議氧秘,那么就添加冒號和要添加的協(xié)議,之后再加大括號趴久,里面寫內(nèi)容丸相。此處的限制如下:

1、擴展不能重寫已經(jīng)存在的成員彼棍。(但是它可以重載已經(jīng)存在的方法)

2灭忠、擴展不能聲明存儲屬性。(但是它可以聲明計算屬性

3座硕、類的擴展不能聲明指定構(gòu)造器析構(gòu)器弛作。(但是它可以聲明便利構(gòu)造器

擴展對象類型:

在真實的編程過程中,為了封裝一些不存在的函數(shù)(通過將它表達為屬性或者方法)华匾,我有時會擴展Swift內(nèi)部類型或者Cocoa類型映琳。這是一些真實app的例子:

在某個紙牌游戲中,我需要進行洗牌蜘拉,而牌儲存在數(shù)組里面萨西。那么我就擴展了Swift的Array,給它一個shuffle方法:


1

再如Cocoa的Core Graphics 框架有很多很有用的函數(shù)與CGRect結(jié)構(gòu)體有關(guān)旭旭,Swift對它有諸多擴展谎脯,不過對于取得CGRect的中心坐標(Center Point : CGPoint),還沒有捷徑可走持寄。所以我就擴展出了center屬性:


2

擴展可以定義static和class方法源梭。由于對象類型常常是全局可用的,所以這不失為是構(gòu)造一個全局函數(shù)的好辦法稍味。比如废麻,如果覺得金色會在開發(fā)中常常使用到,就沒有必要每一次都重復定義仲闽,可以將它封裝在全局函數(shù)中脑溢。然而也不需要直接構(gòu)造一個全局函數(shù),我們可以將他封裝在UIColor中:


3

現(xiàn)在你就可以像調(diào)用UIColor.redcolor一樣,使用UIColor.myGoldenColor來調(diào)用顏色了屑彻。

另一個擴展很好用的地方就是使Cocoa內(nèi)置類和你自己的數(shù)據(jù)類型一起工作验庙。比如在Zotz App中,我定義了一個枚舉類型社牲,用來讀檔存檔粪薛。


4

其中的問題就是,讓我存檔時我需要每次調(diào)用rawValue搏恤。


5

這看起來很丑违寿,所以必須要改。我們可以教會NSCoder(coder的類)怎樣去干活兒熟空。在這個擴展中藤巢,我重載了encoderObject:forKey" 方法:


6

事實上,我將rawValue的調(diào)用從我自己的代碼中放進了NSCoder里∠⒙蓿現(xiàn)在我就可以這樣調(diào)用了:


7

擴展還可以整理對象類型的代碼掂咒。一個常見的應用就是為對象類型增加其采用的協(xié)議。比如這樣:

8

如果你覺得多行定義你的對象類型太復雜迈喉,那么用擴展可以很好地分解代碼绍刮。

當你對Swift的結(jié)構(gòu)體(Struct)進行擴展的時候,一個有趣的事情發(fā)生了:你聲明一個構(gòu)造器挨摸,原先的隱式構(gòu)造器(Implicit initializer)可以保留下來:


9

這段代碼意味著你可以通過顯式構(gòu)造器Digit()孩革,也可以用原先的隱式構(gòu)造器Digit(number:)。這樣即使我們顯式定義了構(gòu)造器得运,也不會使原先的隱式構(gòu)造器消失膝蜈。

擴展協(xié)議(Extending Protocols):

在Swift2.0中,你可以擴展協(xié)議了澈圈!

像擴展其他的對象類型一樣彬檀,你也可以擴展協(xié)議的方法和屬性。不像協(xié)議的聲明中方法和屬性僅僅是要求采用者實現(xiàn)瞬女,擴展協(xié)議會是采用者繼承該方法和協(xié)議窍帝,也就是說它們是真正的方法和屬性。


10

看上面诽偷,Bird可以不用實現(xiàn)fly()就繼承Flier坤学。這是因為Flier協(xié)議的擴展提供了該方法,Bird實際上繼承了fly():


11

采用者可以實現(xiàn)從擴展協(xié)議繼承來的方法报慕,再重寫它:


12

但是請注意:這種繼承不是多態(tài)的深浮。采用者的實現(xiàn)不是重寫;而僅僅是另一個實現(xiàn)眠冈。內(nèi)部識別規(guī)則不適用飞苇,關(guān)鍵是引用菌瘫。

13

即使f在內(nèi)部其實是Insect(用is運算符可以知道),fly消息還是會發(fā)送給Flier布卡。

為了將它變得看起來像多態(tài)繼承雨让,我們必須將fly在原協(xié)議中定義:


14

現(xiàn)在Insect就保持了它的內(nèi)部完整:


15

這種差異是有意義的。因為協(xié)議采用不會引入動態(tài)分配忿等。因此編譯器必須進行靜態(tài)決定栖忠。如果在原協(xié)議中,要求方法被聲明贸街,那么采用者就必須實現(xiàn)它庵寞,所以我們就可以調(diào)用該方法。但是如果該方法僅僅存在于協(xié)議擴展薛匪,這就取決于運行的動態(tài)分配(Dynamic Dispatch)捐川。這就有可能使得協(xié)議落空,所以消息就被發(fā)送到協(xié)議擴展去了蛋辈。

協(xié)議擴展的主要好處就是允許代碼被轉(zhuǎn)移至一個合適的Scope中属拾。這里有一個例子:我有四個枚舉類型将谊,每一個都代表了Card的一個屬性察蹲,F(xiàn)ill搀崭、Color、Shape和Number。他們都有一個人int類型的初始值努释。我對與每次都賦給rawValue有點煩躁了,所以就給每個枚舉類型一個沒有外部參數(shù)名的代理構(gòu)造器纤虽,它們會調(diào)用內(nèi)置的init(rawValue:)構(gòu)造器:


16

盡管我不喜歡這樣的方式狡刘,但是在Swift1.2之前我沒有任何辦法。而現(xiàn)在瓦堵,我可以用協(xié)議擴展來改變這種情況基协。帶有初始值的枚舉類型將會自動采用內(nèi)置的協(xié)議 Rawpresentable,初始值的類型別名叫做RawValue菇用。所以我可以將我的構(gòu)造器加入到此協(xié)議中:

17

在Swift標準庫中澜驮,協(xié)議擴展意味著很多全局函數(shù)可以被改寫為方法。比如惋鸥,在Swift1.2之前杂穷,enumerate是一個全局函數(shù):


18

原先這個函數(shù)只能是全局函數(shù)。

這個函數(shù)只作用于序列(sequence)卦绣,所以也是SequenceType協(xié)議的采用者耐量。在Swift2.0之前,怎樣實現(xiàn)呢滤港?enumerate可能在SequenceType協(xié)議中被定義(requirement)廊蜒,但是這意味著所有的采用者都要實現(xiàn)它,這顯然不可能。所以我們只能把它聲明為一個全局函數(shù)山叮,然后用泛型約束保證入口八堡,用序列作為參數(shù)。

在Swift2.0聘芜,enumerate就可以當做方法定義在SequenceType協(xié)議中了:


19

現(xiàn)在就不需要什么泛型約束了兄渺,也不需要泛型,甚至不需要參數(shù)汰现。被發(fā)送了enumerate消息的序列就是要飆車enumerate的序列挂谍。

這個例子的方法可以被廣泛使用。很多Swift標準庫的全局函數(shù)變成了方法瞎饲。

擴展泛型:

當你擴展泛型類型的時候口叙,占位符類型名對于你的擴展聲明是可見的。你很可能用到它們嗅战。不過這會使你的代碼變得不清楚妄田,因為看起來你在使用沒有被定義過的變量。所以最好加點注釋驮捍。


20

在Swift2.0中疟呐,泛型類型擴展可以包含where語句了。這和泛型約束的效果類似:它限制了決定泛型類型的代碼东且,向編譯器保證你的代碼是合法的启具。

通過協(xié)議擴展,這意味著全局函數(shù)可以用作方法鲁冯。看下面的這個例子:


21

為什么我要用全局函數(shù)呢色查?因為在Swift2.0之前我不得不這么做薯演。如果我想把它(求最小值)變成Array的一個方法,在Swift1.2之前秧了,我可以擴展Array而且也可以引用Array的泛型占位符跨扮,然而它不能進一步限制占位符。所以這里沒有辦法將此方法插入Array并保證該占位符代表的類型是 Comparable示惊,所以編譯器也不允許使用<比較Array的元素好港。而在Swift2.0就大大不同了。不僅可以更進一步地約束泛型類型米罚,而且還可以將它變成Array的方法钧汹。


22

這個方法只能被元素是Comparable的序列調(diào)用,否則編譯器將拒絕它們录择。

第二行不編譯的原因就是因為我沒有使Digit結(jié)構(gòu)體采用Comparable拔莱。

同樣這個改變也使得Swift的標準庫有大規(guī)模的改變碗降,允許把全局函數(shù)寫入結(jié)構(gòu)體擴展或者協(xié)議擴展作為方法。比如塘秦,全局函數(shù)find(在Swift1.2之前)變成了集合類型的indexOf方法讼渊,此方法的元素必須是Equatable。


23

這就是協(xié)議擴展尊剔,同樣也是運用where語句的泛型擴展爪幻,二者在Swift2.0之前都是不被允許的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末须误,一起剝皮案震驚了整個濱河市挨稿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌京痢,老刑警劉巖奶甘,帶你破解...
    沈念sama閱讀 221,331評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異祭椰,居然都是意外死亡臭家,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,372評論 3 398
  • 文/潘曉璐 我一進店門方淤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來钉赁,“玉大人,你說我怎么就攤上這事臣淤¢厦梗” “怎么了?”我有些...
    開封第一講書人閱讀 167,755評論 0 360
  • 文/不壞的土叔 我叫張陵邑蒋,是天一觀的道長。 經(jīng)常有香客問我按厘,道長医吊,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,528評論 1 296
  • 正文 為了忘掉前任逮京,我火速辦了婚禮卿堂,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘懒棉。我一直安慰自己草描,他們只是感情好,可當我...
    茶點故事閱讀 68,526評論 6 397
  • 文/花漫 我一把揭開白布策严。 她就那樣靜靜地躺著穗慕,像睡著了一般。 火紅的嫁衣襯著肌膚如雪妻导。 梳的紋絲不亂的頭發(fā)上逛绵,一...
    開封第一講書人閱讀 52,166評論 1 308
  • 那天怀各,我揣著相機與錄音,去河邊找鬼术浪。 笑死瓢对,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的胰苏。 我是一名探鬼主播硕蛹,決...
    沈念sama閱讀 40,768評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼硕并!你這毒婦竟也來了妓美?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,664評論 0 276
  • 序言:老撾萬榮一對情侶失蹤鲤孵,失蹤者是張志新(化名)和其女友劉穎壶栋,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體普监,經(jīng)...
    沈念sama閱讀 46,205評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡贵试,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,290評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了凯正。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片毙玻。...
    茶點故事閱讀 40,435評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖廊散,靈堂內(nèi)的尸體忽然破棺而出桑滩,到底是詐尸還是另有隱情,我是刑警寧澤允睹,帶...
    沈念sama閱讀 36,126評論 5 349
  • 正文 年R本政府宣布运准,位于F島的核電站,受9級特大地震影響缭受,放射性物質(zhì)發(fā)生泄漏胁澳。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,804評論 3 333
  • 文/蒙蒙 一米者、第九天 我趴在偏房一處隱蔽的房頂上張望韭畸。 院中可真熱鬧,春花似錦蔓搞、人聲如沸胰丁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,276評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽锦庸。三九已至,卻和暖如春妻顶,著一層夾襖步出監(jiān)牢的瞬間酸员,已是汗流浹背蜒车。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留幔嗦,地道東北人酿愧。 一個月前我還...
    沈念sama閱讀 48,818評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像邀泉,于是被迫代替她去往敵國和親嬉挡。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,442評論 2 359

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

  • importUIKit classViewController:UITabBarController{ enumD...
    明哥_Young閱讀 3,817評論 1 10
  • 136.泛型 泛型代碼讓你可以寫出靈活,可重用的函數(shù)和類型,它們可以使用任何類型,受你定義的需求的約束汇恤。你可以寫出...
    無灃閱讀 1,476評論 0 4
  • 擴展 擴展就是向一個已有的類庞钢、結(jié)構(gòu)體、枚舉類型或者協(xié)議類型添加新功能因谎。這包括在沒有權(quán)限獲取原始源代碼的情況下擴展類...
    cht005288閱讀 467評論 0 0
  • Hello Word 在屏幕上打印“Hello, world”基括,可以用一行代碼實現(xiàn): 你不需要為了輸入輸出或者字符...
    restkuan閱讀 3,188評論 0 6
  • Swift屬性 Swift屬性將值跟特定的類,結(jié)構(gòu)體财岔,枚舉關(guān)聯(lián)风皿。分為存儲屬性和計算屬性,通常用于特定類型的實例匠璧。屬...
    小小廚師閱讀 855評論 0 0