Swift學(xué)習(xí)之路-Extension

本文首發(fā)地址
請?jiān)陂喿x本文章時(shí)次和,順手將文中的示例代碼在playground中敲一遍反肋,這樣能加深理解!Lな石蔗!
閱讀該文章大約需要:15分鐘
讀完之后你能獲得:
1、Extension是什么
2畅形、它能做什么

本文全部內(nèi)容基于Swift版本:3.0.1

Extension的基本語法

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

Tip:擴(kuò)展可以為一個(gè)類型添加新的功能养距,但是不能重寫已有的功能。

struct Student {
    var name = ""
    var age = 1
    func print() {
        
    }
}

extension Student {
    //改行會報(bào)錯(cuò)`invalid redeclaration print()`重復(fù)聲明print()日熬,重寫變量也是不行的棍厌。
    func print() {
    }
}

Swift中的Extension可以做什么

我們想知道Extension在Swift中能做些什么,最直接的方法就是查看Swift的官方文檔了竖席。下面是文檔中指出Extension能做的六個(gè)方面耘纱。

  • 添加計(jì)算型實(shí)例屬性和計(jì)算型類型屬性
  • 定義實(shí)例方法和類型方法
  • 提供新的構(gòu)造器
  • 定義下標(biāo)
  • 定義和使用新的嵌套類型
  • 使已存在的類型遵守某個(gè)協(xié)議

看完上面Extension能做的六個(gè)方面,我們來逐條解釋說明一下:

添加計(jì)算型實(shí)例屬性和計(jì)算型類型屬性

首先我們要了解什么是計(jì)算型屬性毕荐,計(jì)算型屬性(computed property)不直接存儲值束析,而是提供一個(gè)getter和一個(gè)可選的setter,來間接獲取和設(shè)置其他屬性或變量的值憎亚。關(guān)于更多的計(jì)算型屬性的內(nèi)容請自行查看官方文檔员寇,在此不再贅述。那么我們什么場景可以用到這個(gè)功能呢虽填?舉一個(gè)最常見的例子丁恭,當(dāng)你想訪問某個(gè)view的width的時(shí)候,通常情況下你會這么寫:

view.frame.size.width

但是這樣寫很長很不方便斋日,作為一個(gè)懶惰的程序員牲览,這時(shí)候你就要想我能不能縮短訪問該屬性的代碼。不要猶豫了騷年,這時(shí)候你只需要寫一個(gè)UIView的Extension就可以達(dá)到你的目的第献。

extension UIView {
    var x: CGFloat { return self.frame.origin.x }
    var y: CGFloat { return self.frame.origin.y }
    var width: CGFloat { return self.frame.size.width }
    var height: CGFloat { return self.frame.size.height }
}

這樣你就可以通過來訪問該屬性贡必。怎么樣庸毫,有沒有感受到Extension的便利之處仔拟。

view.width

定義實(shí)例方法和類型方法

在你辛辛苦苦寫完一個(gè)Student類后,萬惡的產(chǎn)品過來告訴你需求改了飒赃,這時(shí)雖然你心中有一萬只草泥馬在奔騰利花,但是為了心中那份神圣的程序員的責(zé)任感(當(dāng)然還有糊口的工資),你還是要修改代碼载佳。如果你想在不改變原始類的基礎(chǔ)上添加功能炒事,那你可以給Student類添加Extension來解決問題。

Tip:這里值得注意的一點(diǎn)是在Swift中蔫慧,Extension可以給類和類型添加挠乳,比如你也可以給一個(gè)struct添加Extension,而在Objective-C中姑躲,你只能給類添加Extension睡扬。

class Student {
    var name = ""
    var age = 1
}

extension Student {
    func printCurrentStudentName() {
        print(self.name)
    }
}

var jack = Student()
jack.name = "jack"
jack.printCurrentStudentName()

提供新的構(gòu)造器(Initializers)

最常見的Rect通常由originsize來構(gòu)造初始化,但是如果在你寫完Rect的定義后黍析,你偏偏想要通過center和size來確定Rect(作為一個(gè)程序員就要有一種作死的精神)卖怜,那你就要用Extension來給Rect提供一個(gè)新的構(gòu)造器。關(guān)于更多關(guān)于構(gòu)造器的信息橄仍,請參考官方文檔

本例子來源官方文檔

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()
}

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

通過Extension來給Rect添加一個(gè)新的構(gòu)造器韧涨。

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)
    }
}

這樣你就可以通過新的構(gòu)造器來初始化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)

定義下標(biāo)

通過Swift中的Extension侮繁,你可以給已知類型添加下標(biāo)虑粥。例如下面的例子就是給Int類型添加一個(gè)下標(biāo),該下標(biāo)表示十進(jìn)制數(shù)從右向左的第n個(gè)數(shù)字宪哩。

本例子來源官方文檔

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

定義和使用新的嵌套類型(nest type)

Extensions可以給已知的類娩贷、結(jié)構(gòu)體、枚舉添加嵌套類型锁孟。下面的例子是給Int類型添加一個(gè)判斷正負(fù)數(shù)的Extension彬祖,該Extension嵌套一個(gè)枚舉。

本例子來源官方文檔

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
        }
    }
}

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 + "

使已存在的類型遵守某個(gè)協(xié)議

編寫使該類型遵守某個(gè)協(xié)議的Extension的語法如下:

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

示例代碼:

protocol StudentProtocol {
    var address: String { get }
}

struct Student {
    var name = ""
    var age = 1
    
}

extension Student: StudentProtocol {
    var address: String {
        return "address"
    }
}

var jack = Student()
jack.address
//輸出 address

若添加Extension的類型已經(jīng)實(shí)現(xiàn)協(xié)議中的內(nèi)容品抽,你可以寫一個(gè)空的Extension來遵守協(xié)議:

protocol StudentProtocol {
    var address: String { get }
}

struct Student {
    var address: String {
        return "address"
    }
    var name = ""
    var age = 1
}

extension Student: StudentProtocol {}

var jack = Student()
jack.address
//輸出 address

總結(jié)

  • Extension可以為一個(gè)已有的類储笑、結(jié)構(gòu)體、枚舉類型或者協(xié)議類型添加新功能圆恤。
  • 可以在沒有權(quán)限獲取原始源代碼的情況下擴(kuò)展類型的內(nèi)容
  • Extendion和Objective-C中的Category類似突倍。(OC中的Category有名字,Swift中的擴(kuò)展沒有名字)

下篇預(yù)告:Swift-Protocol

若本文有何錯(cuò)誤或者不當(dāng)之處,還望不吝賜教羽历。謝謝焊虏!

Swift-Extension的官方文檔

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市秕磷,隨后出現(xiàn)的幾起案子诵闭,更是在濱河造成了極大的恐慌,老刑警劉巖澎嚣,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件疏尿,死亡現(xiàn)場離奇詭異,居然都是意外死亡币叹,警方通過查閱死者的電腦和手機(jī)润歉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來颈抚,“玉大人,你說我怎么就攤上這事嚼鹉》泛海” “怎么了?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵锚赤,是天一觀的道長匹舞。 經(jīng)常有香客問我,道長线脚,這世上最難降的妖魔是什么赐稽? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮浑侥,結(jié)果婚禮上姊舵,老公的妹妹穿的比我還像新娘。我一直安慰自己寓落,他們只是感情好括丁,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著伶选,像睡著了一般史飞。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上仰税,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天构资,我揣著相機(jī)與錄音,去河邊找鬼陨簇。 笑死吐绵,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播拦赠,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼巍沙,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了荷鼠?” 一聲冷哼從身側(cè)響起句携,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎允乐,沒想到半個(gè)月后矮嫉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡牍疏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年蠢笋,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鳞陨。...
    茶點(diǎn)故事閱讀 38,617評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡昨寞,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出厦滤,到底是詐尸還是另有隱情援岩,我是刑警寧澤,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布掏导,位于F島的核電站享怀,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏趟咆。R本人自食惡果不足惜添瓷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望值纱。 院中可真熱鬧鳞贷,春花似錦、人聲如沸计雌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽凿滤。三九已至妈橄,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間翁脆,已是汗流浹背眷蚓。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留反番,地道東北人沙热。 一個(gè)月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓叉钥,卻偏偏與公主長得像,于是被迫代替她去往敵國和親篙贸。 傳聞我的和親對象是個(gè)殘疾皇子投队,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評論 2 348

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

  • 132.轉(zhuǎn)換錯(cuò)誤成可選值 通過轉(zhuǎn)換錯(cuò)誤成一個(gè)可選值,你可以使用 try? 來處理錯(cuò)誤。當(dāng)執(zhí)行try?表達(dá)式時(shí),如果...
    無灃閱讀 1,244評論 0 3
  • Swift屬性 Swift屬性將值跟特定的類爵川,結(jié)構(gòu)體敷鸦,枚舉關(guān)聯(lián)。分為存儲屬性和計(jì)算屬性寝贡,通常用于特定類型的實(shí)例扒披。屬...
    小小廚師閱讀 846評論 0 0
  • importUIKit classViewController:UITabBarController{ enumD...
    明哥_Young閱讀 3,783評論 1 10
  • 基礎(chǔ)部分(The Basics) 當(dāng)推斷浮點(diǎn)數(shù)的類型時(shí),Swift 總是會選擇Double而不是Float圃泡。 結(jié)合...
    gamper閱讀 1,272評論 0 7
  • 又到婺源油菜花開的季節(jié)碟案,她端著咖啡站在窗前,看著手機(jī)里別人的朋友圈颇蜡,滿屏綻放的油菜花价说,想起那一年,她和他风秤,...
    天堂里的細(xì)雨霏霏閱讀 280評論 0 1