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

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

本文全部?jī)?nèi)容基于Swift版本:3.0.1

Extension的基本語(yǔ)法

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

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

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

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

Swift中的Extension可以做什么

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

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

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

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

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

view.frame.size.width

但是這樣寫(xiě)很長(zhǎng)很不方便,作為一個(gè)懶惰的程序員,這時(shí)候你就要想我能不能縮短訪問(wèn)該屬性的代碼。不要猶豫了騷年,這時(shí)候你只需要寫(xiě)一個(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 }
}

這樣你就可以通過(guò)來(lái)訪問(wèn)該屬性。怎么樣,有沒(méi)有感受到Extension的便利之處。

view.width

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

在你辛辛苦苦寫(xiě)完一個(gè)Student類后,萬(wàn)惡的產(chǎn)品過(guò)來(lái)告訴你需求改了,這時(shí)雖然你心中有一萬(wàn)只草泥馬在奔騰,但是為了心中那份神圣的程序員的責(zé)任感(當(dāng)然還有糊口的工資),你還是要修改代碼。如果你想在不改變?cè)碱惖幕A(chǔ)上添加功能,那你可以給Student類添加Extension來(lái)解決問(wèn)題。

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)

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

本例子來(lái)源官方文檔

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

通過(guò)Extension來(lái)給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)
    }
}

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

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

本例子來(lái)源官方文檔

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è)枚舉。

本例子來(lái)源官方文檔

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é)議

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

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)容,你可以寫(xiě)一個(gè)空的Extension來(lái)遵守協(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é)議類型添加新功能。
  • 可以在沒(méi)有權(quán)限獲取原始源代碼的情況下擴(kuò)展類型的內(nèi)容
  • Extendion和Objective-C中的Category類似。(OC中的Category有名字,Swift中的擴(kuò)展沒(méi)有名字)

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

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

Swift-Extension的官方文檔

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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