swift簡單總結(三十一)—— 擴展

版本記錄

版本號 時間
V1.0 2017.08.01

前言

我是swift2.0的時候開始接觸的,記得那時候還不是很穩定,公司的項目也都是用oc做的,并不對swift很重視,我自己學了一段時間,到現在swift3.0+已經出來了,自己平時也不寫,忘記的也差不多了,正好項目這段時間已經上線了,不是很忙,我就可以每天總結一點了,希望對自己對大家有所幫助。在總結的時候我會對比oc進行說明,有代碼的我會給出相關比對代碼。
1. swift簡單總結(一)—— 數據簡單值和類型轉換
2. swift簡單總結(二)—— 簡單值和控制流
3. swift簡單總結(三)—— 循環控制和函數
4. swift簡單總結(四)—— 函數和類
5. swift簡單總結(五)—— 枚舉和結構體
6. swift簡單總結(六)—— 協議擴展與泛型
7. swift簡單總結(七)—— 數據類型
8. swift簡單總結(八)—— 別名、布爾值與元組
9. swift簡單總結(九)—— 可選值和斷言
10. swift簡單總結(十)—— 運算符
11. swift簡單總結(十一)—— 字符串和字符
12. swift簡單總結(十二)—— 集合類型之數組
13. swift簡單總結(十三)—— 集合類型之字典
14. swift簡單總結(十四)—— 控制流
15. swift簡單總結(十五)—— 控制轉移語句
16. swift簡單總結(十六)—— 函數
17. swift簡單總結(十七)—— 閉包(Closures)
18. swift簡單總結(十八)—— 枚舉
19. swift簡單總結(十九)—— 類和結構體
20. swift簡單總結(二十)—— 屬性
21. swift簡單總結(二十一)—— 方法
22. swift簡單總結(二十二)—— 下標腳本
23. swift簡單總結(二十三)—— 繼承
24. swift簡單總結(二十四)—— 構造過程
25. swift簡單總結(二十五)—— 構造過程
26. swift簡單總結(二十六)—— 析構過程
27. swift簡單總結(二十七)—— 自動引用計數
28. swift簡單總結(二十八)—— 可選鏈
29. swift簡單總結(二十九)—— 類型轉換
30.swift簡單總結(三十)—— 嵌套類型

擴展 - Extensions

擴展就是向一個已有的類、結構體或枚舉類型添加新功能,這包括在沒有權限獲取原始源代碼的情況下擴展類型的能力(即逆向建模),擴展和OC中的分類類似,不過不同的是,swift的擴展是沒有名字的。

swift中的擴展可以:

  • 添加計算型屬性和計算靜態屬性
  • 定義實例方法和類型方法
  • 提供新的構造器
  • 定義下標
  • 定義和使用新的嵌套類型
  • 使一個已有類型符合某個協議

注意:如果你定義了一個已有類型添加新功能,那么這個新功能對該類型的所有已有實例中都是可用的,即使他們是在你的這個擴展的前面定義的。

本篇主要從以下幾個方面進行說明。

  • 擴展語法
  • 計算型屬性
  • 構造器
  • 方法
  • 下標
  • 嵌套類型

擴展語法 - Extension Syntax

下面先看一下如何聲明一個擴展。

extension SomeType {
    //加到SomeType的新功能代碼
}

一個擴展可以擴展一個已有來行,使其能夠適配一個或多個協議,當這種情況發生時,協議的名字應該完全按照類或結構體的名字方式進行書寫。

extension SomeType : SomeProtocol, AnotherProtocol {
    //加到SomeType的新功能代碼
}

按照這種方式添加的協議遵循者(protocol comformance)被稱為在擴展中添加協議遵循者。


計算性屬性 - Computed Properties

擴展可以向已有類型添加計算性實例屬性和計算型類型屬性,下面就是向swift內部的Double類型加入幾個計算型實例屬性。

下面看一下代碼。

class JJPracticeVC: UIViewController {

    override func viewDidLoad()
    {
        super.viewDidLoad()

        view.backgroundColor = UIColor.lightGray
        
        let oneInch = 25.4.mm
        print("One inch is \(oneInch) meters")
        
        let threeFeet = 3.ft
        print("Three feet is \(threeFeet) meters")
    }
}

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

下面看輸出結果

One inch is 0.0254 meters
Three feet is 0.914399970739201 meters

這些屬性是只讀的計算型屬性,所以考慮他們不用get關鍵字,它們的返回值是Double類型。


構造器 - Initializers

擴展可以向已有類型添加新的構造器,這可以讓你擴展其他類型,將你自己的定制類型作為構造參數,或者提供該類型的原始實現中沒有包含的額外初始化選項。

擴展能向類中添加新的便利構造器,但是它們不能向類中添加新的指定構造器或析構函數,指定構造器和析構函數必須總是由原始的類實現來提供。

下面的例子給出的就是描述幾何矩形的定制結構體Rect,下面看一下簡單的代碼。

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提供了其所有屬性的默認值,所以正如默認構造器中描述的,它可以自動接受一個默認的構造器和一個成員級構造器,這些構造器可以用于構造新的Rect實例。

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

你可以提供一個額外的使用特殊中心點和大小的構造器來擴展Rect結構體。

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

這個新的構造器首先根據提供的centersize值計算一個合適的點,然后調用該結構體自動的成員構造器init(origin: size:),該構造器將新的原點和大小存到了合適的屬性中。

class JJPracticeVC: UIViewController {

    override func viewDidLoad()
    {
        super.viewDidLoad()

        view.backgroundColor = UIColor.lightGray
        
        let centerRect = Rect(center: Point(x : 4.0, y : 4.0), size: Size(width: 3.0, height: 3.0))
        print(centerRect)
    }
}

下面看輸出結果

Rect(origin: JJSwift.Point(x: 2.5, y: 2.5), size: JJSwift.Size(width: 3.0, height: 3.0))

注意:如果你使用擴展提供了一個新的構造器,你依舊有責任保證構造過程能夠讓所有勢力完全初始化。


方法 - Methods

擴展可以向已有類型添加新的實例方法和類型方法,下面的例子向Int類型添加一個新的實例方法repetitions。

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

這個repetitions方法使用了一個() -> ()類型的單參數,表明函數沒有參數而且沒有返回值,定義該擴展后,你就可以對任意整數調用repetitions方法,進行多次執行某個任務。

下面我們就調用下試試。

class JJPracticeVC: UIViewController {

    override func viewDidLoad()
    {
        super.viewDidLoad()

        view.backgroundColor = UIColor.lightGray
        
        3.repetitions {
            print("Hello")
        }
    }
}

下面看輸出結果

Hello
Hello
Hello

上面其實就是尾隨閉包。

1. 修改實例方法 - Mutating Instance Methods

通過擴展添加的實例方法也可以修改該實例本身,結構體和枚舉類型中修改self或其屬性的方法必須將該實例方法標注為mutating,正如來自原始實現的修改方法一樣。

下面的例子給Int類型添加了一個新的名字為square的修改方法,來實現一個原始值的平方計算。

class JJPracticeVC: UIViewController {

    override func viewDidLoad()
    {
        super.viewDidLoad()

        view.backgroundColor = UIColor.lightGray
        
        var someInt = 3
        someInt.square()
        print(someInt)
    }
}

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

下面看輸出結果

9

下標 - Subscripts

擴展可以向一個已有類型添加新下標,看下面的例子,向Int添加了一個整型下標,該下標[n]返回十進制數字從右向左的第n個數字。例如123456789[0]返回9。

下面看一下代碼。

class JJPracticeVC: UIViewController {

    override func viewDidLoad()
    {
        super.viewDidLoad()

        view.backgroundColor = UIColor.lightGray
        
        print(123456789[0])
    }
}

extension Int{
    subscript( digitIndex : Int) -> Int{
        var index = digitIndex
        var decimalBase = 1
        while index > 0 {
            decimalBase *= 10
            index -= 1
        }
        return (self/decimalBase) % 10
    }
}

下面看輸出結果

9

如果該Int值沒有足夠的位數,下標越界,那么上述實現的下標會返回0,因為它會在數字左邊自動補0。

print(123456789[10])

下面看輸出結果

0

嵌套類型 - Nested Types

擴展可以向已有的類、結構體和枚舉添加新的嵌套類型。

extension Character{
    enum Kind {
        case Vowel, Consonaut, Other
    }
    
    var kind : Kind{
        switch String(self).lowercased() {
        case "a", "e", "i", "o", "u":
            return .Vowel
        case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m","n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z":
            return .Consonaut
        default:
            return .Other
        }
    }
}

該例子向Character添加了新的嵌套枚舉,這個名為kind的枚舉表示特定字符的類型,這個例子還添加了一個新的計算實例屬性kind,用來返回合適的kind枚舉成員。

下面我們調用一下。

class JJPracticeVC: UIViewController {

    override func viewDidLoad()
    {
        super.viewDidLoad()

        view.backgroundColor = UIColor.lightGray
        
        printLetterKinds(word: "Hello")
    }
}

func printLetterKinds(word : String){
    print("\(word) is made up of the following kinds of letters")
    for character in word.characters {
        switch character.kind {
        case .Vowel:
            print("vowel")
        case .Consonaut:
            print("consonaut")
        default:
            print("other")
        }
    }
}

下面看輸出結果

Hello is made up of the following kinds of letters
consonaut
vowel
consonaut
consonaut
vowel

這個很好理解,相信大家都可以看的明白。

后記

未完,待續~~~

山水之樂
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,119評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,382評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,038評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,853評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,616評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,112評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,192評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,355評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,869評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,727評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,928評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,467評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,165評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,570評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,813評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,585評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,892評論 2 372

推薦閱讀更多精彩內容