【Swift 3.1】21 - 擴展 (Extensions)

【Swift 3.1】21 - 擴展 (Extensions)

自從蘋果2014年發(fā)布Swift尘惧,到現(xiàn)在已經(jīng)兩年多了康栈,而Swift也來到了3.1版本。去年利用工作之余,共花了兩個多月的時間把官方的Swift編程指南看完∩睹矗現(xiàn)在整理一下筆記登舞,回顧一下以前的知識。有需要的同學(xué)可以去看官方文檔>>悬荣。


擴展可以在已經(jīng)存在的類菠秒、結(jié)構(gòu)、枚舉或者協(xié)議上添加新的功能氯迂。Swift的擴展類似于OC的分類(不同于OC的是践叠,Swift的擴展沒有名字)。

Swift的擴展可以:

  • 添加實例計算屬性和類型計算屬性
  • 添加實例方法和類型方法
  • 提供新的初始化器
  • 定義下標(biāo)
  • 定義并使用新的嵌套類型
  • 讓一個已經(jīng)存在的類遵循一個協(xié)議

注意: 擴展可以添加新的功能嚼蚀,但是不能重寫已經(jīng)存在的方法禁灼。

擴展語法 (Extension Syntax)

使用extension關(guān)鍵字:

extension SomeType {
    // new functionality to add to SomeType goes here
}

可以使用擴展讓一個已經(jīng)存在的類遵循一個或多個協(xié)議:

extension SomeType: SomeProtocol, AnotherProtocol {
    // implementation of protocol requirements goes here
}

注意:如果定義一個擴展添加新的功能到已經(jīng)存在的類,那么這個存在的類的所有實例都可以使用這些新的方法轿曙。即使他們是在定義擴展之前創(chuàng)建的弄捕。

計算屬性 (Computed Properties)

下面是一個例子:

extension Double {
    var km: Double { return self * 1_000.0 }
    var m: Double { return self }
    var cm: Double { return self / 100.0 }
    var mm: Double { return self / 1_000.0 }
    var ft: Double { return self / 3.28084 }
}
let oneInch = 25.4.mm
print("One inch is \(oneInch) meters")
// Prints "One inch is 0.0254 meters"
let threeFeet = 3.ft
print("Three feet is \(threeFeet) meters")
// Prints "Three feet is 0.914399970739201 meters"

所有新添加的屬性都是只讀屬性返回值都是Double類型,可以使用加號直接相加:

let aMarathon = 42.km + 195.m
print("A marathon is \(aMarathon) meters long")
// Prints "A marathon is 42195.0 meters long"

注意:擴展可以添加新的計算屬性拳芙,但是不能添加存儲屬性或者添加屬性觀察者到已經(jīng)存在的屬性察藐。

初始化器 (Initializers)

擴展可以為一個類添加新的便利初始化器,但是不能添加指定初始化器或者反初始化器到舟扎。

注意:一個值類型為所有存儲屬性都提供默認值分飞,并且沒有自定義初始化器,如果我們使用擴展添加初始化器到這個值類型中睹限,我們可以在擴展中調(diào)用默認的初始化器和逐一成員初始化器譬猫。

下面是一個例子:

struct Size {
    var width = 0.0, height = 0.0
}
struct Point {
    var x = 0.0, y = 0.0
}
struct Rect {
    var origin = Point()
    var size = Size()
}

因為Rect結(jié)構(gòu)為所有屬性提供了默認值,所以它自動獲得默認初始化器和一個逐一成員初始化器羡疗。

let defaultRect = Rect()
let memberwiseRect = Rect(origin: Point(x: 2.0, y: 2.0),
                          size: Size(width: 5.0, height: 5.0))

我們可以使用擴展來提供另外一個初始化器:

extension Rect {
    init(center: Point, size: Size) {
        let originX = center.x - (size.width / 2)
        let originY = center.y - (size.height / 2)
        self.init(origin: Point(x: originX, y: originY), size: size)
    }
}

可以在擴展的初始化器實現(xiàn)中調(diào)用逐一成員初始化器染服。用擴展的初始化器創(chuàng)建一個Rect實例:

let centerRect = Rect(center: Point(x: 4.0, y: 4.0),
                      size: Size(width: 3.0, height: 3.0))
// centerRect's origin is (2.5, 2.5) and its size is (3.0, 3.0)

方法 (Methods)

添加一個實例方法:

extension Int {
    func repetitions(task: () -> Void) {
        for _ in 0..<self {
            task()
        }
    }
}

// 使用Int實例調(diào)用擴展的方法
3.repetitions {
    print("Hello!")
}
// Hello!
// Hello!
// Hello!

Mutating 實例方法 (Mutating Instance Methods)

使用擴展添加的實例方法也可以改變實例自己。修改self或者它的屬性的結(jié)構(gòu)和枚舉方法必須標(biāo)記為mutating叨恨。

extension Int {
    mutating func square() {
        self = self * self
    }
}

var someInt = 3
someInt.square()
// someInt is now 9

下標(biāo) (Subscripts)

擴展可以添加新的下標(biāo)柳刮。下面這個例子添加下標(biāo)到Int類型中。下標(biāo)[n]方法從右往左數(shù)的第n個位置的數(shù)字:

  • 123456789[0]返回9
  • 123456789[1]返回8
  • ......
extension Int {
    subscript(digitIndex: Int) -> Int {
        var decimalBase = 1
        for _ in 0..<digitIndex {
            decimalBase *= 10
        }
        return (self / decimalBase) % 10
    }
}
746381295[0]
// returns 5
746381295[1]
// returns 9
746381295[2]
// returns 2
746381295[8]
// returns 7

如果下標(biāo)索引大于Int數(shù)字的位數(shù)痒钝,那么返回值為0

746381295[9]
// returns 0, as if you had requested:
0746381295[9]

嵌套類型 (Nested Types)

擴展可以添加嵌套類型到已經(jīng)存在的類秉颗、結(jié)構(gòu)和枚舉中:

extension Int {
    enum Kind {
        case negative, zero, positive
    }
    var kind: Kind {
        switch self {
        case 0:
            return .zero
        case let x where x > 0:
            return .positive
        default:
            return .negative
        }
    }
}

嵌套的枚舉可以用于Int值中:

func printIntegerKinds(_ numbers: [Int]) {
    for number in numbers {
        switch number.kind {
        case .negative:
            print("- ", terminator: "")
        case .zero:
            print("0 ", terminator: "")
        case .positive:
            print("+ ", terminator: "")
        }
    }
    print("")
}
printIntegerKinds([3, 19, -27, 0, -6, 0, 7])
// Prints "+ + - 0 - 0 + "

第二十一部分完。下個部分:【Swift 3.1】22 - 協(xié)議 (Protocols)


如果有錯誤的地方送矩,歡迎指正蚕甥!謝謝!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末栋荸,一起剝皮案震驚了整個濱河市菇怀,隨后出現(xiàn)的幾起案子凭舶,更是在濱河造成了極大的恐慌,老刑警劉巖爱沟,帶你破解...
    沈念sama閱讀 212,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件帅霜,死亡現(xiàn)場離奇詭異,居然都是意外死亡钥顽,警方通過查閱死者的電腦和手機义屏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蜂大,“玉大人闽铐,你說我怎么就攤上這事∧唐郑” “怎么了兄墅?”我有些...
    開封第一講書人閱讀 158,369評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長澳叉。 經(jīng)常有香客問我隙咸,道長,這世上最難降的妖魔是什么成洗? 我笑而不...
    開封第一講書人閱讀 56,799評論 1 285
  • 正文 為了忘掉前任五督,我火速辦了婚禮,結(jié)果婚禮上瓶殃,老公的妹妹穿的比我還像新娘充包。我一直安慰自己,他們只是感情好遥椿,可當(dāng)我...
    茶點故事閱讀 65,910評論 6 386
  • 文/花漫 我一把揭開白布基矮。 她就那樣靜靜地躺著,像睡著了一般冠场。 火紅的嫁衣襯著肌膚如雪家浇。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,096評論 1 291
  • 那天碴裙,我揣著相機與錄音钢悲,去河邊找鬼。 笑死舔株,一個胖子當(dāng)著我的面吹牛莺琳,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播督笆,決...
    沈念sama閱讀 39,159評論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼芦昔,長吁一口氣:“原來是場噩夢啊……” “哼诱贿!你這毒婦竟也來了娃肿?” 一聲冷哼從身側(cè)響起咕缎,我...
    開封第一講書人閱讀 37,917評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎料扰,沒想到半個月后凭豪,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,360評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡晒杈,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,673評論 2 327
  • 正文 我和宋清朗相戀三年嫂伞,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拯钻。...
    茶點故事閱讀 38,814評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡帖努,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出粪般,到底是詐尸還是另有隱情拼余,我是刑警寧澤,帶...
    沈念sama閱讀 34,509評論 4 334
  • 正文 年R本政府宣布亩歹,位于F島的核電站匙监,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏小作。R本人自食惡果不足惜亭姥,卻給世界環(huán)境...
    茶點故事閱讀 40,156評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望顾稀。 院中可真熱鬧达罗,春花似錦、人聲如沸础拨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽诡宗。三九已至滔蝉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間塔沃,已是汗流浹背蝠引。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蛀柴,地道東北人螃概。 一個月前我還...
    沈念sama閱讀 46,641評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像鸽疾,于是被迫代替她去往敵國和親吊洼。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,728評論 2 351

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

  • importUIKit classViewController:UITabBarController{ enumD...
    明哥_Young閱讀 3,788評論 1 10
  • 官方文檔 初始化 Initialization是為準(zhǔn)備使用類制肮,結(jié)構(gòu)體或者枚舉實例的一個過程冒窍。這個過程涉及了在實例里...
    hrscy閱讀 1,133評論 0 1
  • Swift屬性 Swift屬性將值跟特定的類递沪,結(jié)構(gòu)體,枚舉關(guān)聯(lián)综液。分為存儲屬性和計算屬性款慨,通常用于特定類型的實例。屬...
    小小廚師閱讀 851評論 0 0
  • 123.繼承 一個類可以從另外一個類繼承方法,屬性和其他特征谬莹。當(dāng)一個類繼承另外一個類時, 繼承類叫子類, 被繼承的...
    無灃閱讀 1,385評論 2 4
  • 在中心幼兒園做了六年阿姨附帽,給我最深刻的印象就是雜亂無章埠戳。 領(lǐng)導(dǎo)往往朝令夕改,于是乎我就找不到方向了蕉扮。 ...
    81d1aa263da清風(fēng)閱讀 191評論 4 0