Swift學習:擴展

本篇將詳細總結介紹Swift擴展的用法;
擴展就是為一個已有的類、結構體、枚舉類型或者協(xié)議類型添加新功能。這包括在沒有權限獲取原始源代碼的情況下擴展類型的能力(即逆向建模 )

主要內(nèi)容:
1.理解擴展
2.擴展的基本使用
3.嵌套類型
4.擴展系統(tǒng)類庫

一、理解擴展

1.1擴展特點:

1.擴展和 Objective-C 中的分類類似。(與 Objective-C 不同的是,Swift 的擴展沒有名字。)
3.擴展可以為一個類型添加新的功能,但是不能重寫已有的功能

1.2擴展功能:

1、添加計算型實例屬性和計算型類型屬性。
2、定義實例方法和類型方法
3、提供新便利構造器和便利析構器
4、定義下標
5、定義和使用新的嵌套類型
6、使一個已有類型符合某個協(xié)議”

1.3使用注意:

1.不可以添加存儲屬性,也不可以為已有屬性添加屬性觀察器
2.擴展中不能為類添加新的指定構造器,因為指定構造器和析構器必須由原始的類來實現(xiàn)
3.擴展可以為一個類型添加新的功能,但是不能重寫已有的功能。
4.通過擴展為一個已有類型添加新功能,那么新功能對該類型的所有已有實例都是可用的,即使它們是在這個擴展定義之前創(chuàng)建的。

二、擴展的基本使用

定義如下的Point 、Size、Rectangle,并對其進行擴展。

struct  Point{
    var x = 0.0
    var y = 0.0
}

struct Size{
    var width = 0.0
    var height = 0.0
}

class Rectangle {
    var origin:Point = Point()
    var size = Size()
    init (origin:Point, size: Size){
        self.origin = origin
        self.size = size
    }
}

2.1.擴展屬性

擴展可以添加新的計算型屬性,但是不可以添加存儲型屬性,也不可以為已有屬性添加屬性觀察器

extension Rectangle{
    //注意:擴展不能擴展存儲型屬性
    //var center:Point = Point() //報錯
    //只能擴展計算型屬性
    var center: Point {
        get {
            let center_x = origin.x + size.width/2
            let center_y = origin.y + size.height/2
            return Point(x: center_x, y: center_y)
        }
        set{
            origin.x = newValue.x - size.width/2
            origin.y = newValue.y - size.height/2
        }
    }
}

let rect1 = Rectangle(origin: Point(x:0,y:0), size: Size(width: 100, height: 100))
print(rect1.center)              //Point(x: 50.0, y: 50.0)
rect1.center = Point(x: 0, y: 0)
print(rect1.center)              //Point(x: 0.0, y: 0.0)

2.2.擴展方法

擴展可以為已有類型添加新的實例方法和類型方法。

extension Rectangle{
    //注意:這里直接修改了屬性,如果是結構體Struct,不能直接這樣修改
    //func之前需要使用 mutating
    func translate(x:Double , y:Double){
        self.origin.x += x
        self.origin.y += y
    }
}

let rect2  = Rectangle(origin: Point(x:0,y:0), size: Size(width: 100, height: 100))
rect2.translate(x: 100, y: 100)
print(rect2.center)     //Point(x: 150.0, y: 150.0)

2.3.擴展構造器

擴展能為類添加新的便利構造器,但是它們不能為類添加新的指定構造器或析構器。指定構造器和析構器必須總是由原始的類實現(xiàn)提供.

extension Rectangle{
    //注意:在擴展中添加了構造函數(shù),必須是便利構造函數(shù),其中調(diào)用指定構造函數(shù)
    convenience init(center:Point, size:Size) {
        let origin_x = center.x - size.width/2
        let origin_y = center.y - size.height/2
        //便利構造函數(shù)必須調(diào)用指定構造函數(shù)
        self.init(origin:Point(x: origin_x, y: origin_y),size:size)
    }
}


let rect3 = Rectangle(center: Point(x:200, y:200), size: Size(width: 100, height: 100))

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

注意2:如果你使用擴展為一個值類型添加構造器,同時該值類型的原始實現(xiàn)中未定義任何定制的構造器且所有存儲屬性提供了默認值,那么我們就可以在擴展中的構造器里調(diào)用默認構造器和逐一成員構造器。

2.4.擴展下標

擴展可以為已有類型添加新下標。下面的例子為Swift內(nèi)建類型Int添加了一個整型下標。該下標 [n] 返回十進制數(shù)字從右向左數(shù)的第n個數(shù)字:

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

 //測試代碼:
print(746381295[3]) //1
print(746381295[6]) //6

三、嵌套類型

擴展可以為已有的類、結構體和枚舉添加新的嵌套類型。在下面的示例中,Rectangle中就嵌套一個枚舉類型,用以獲取矩形的各個定點坐標。

extension Rectangle{
    enum Vertex:Int {
        case TopLeft
        case TopRight
        case BottomLeft
        case BottomRight
    }
    
    //擴展出一個方法來獲取各個頂點坐標
    func pointAtVertex(v:Vertex) -> Point{
        switch v {
        case .TopLeft:
            return origin
        case .TopRight:
            return Point(x: origin.x + size.width, y: origin.y)
        case .BottomLeft:
            return Point(x: origin.x, y: origin.y + size.height)
        case .BottomRight:
            return Point(x: origin.x + size.width, y: origin.y + size.height)
        }
    }
    
    //擴展下標
    subscript (index:Int) ->Point{
        assert(index >= 0 && index<4,"out of range")
        //修改枚舉的原始值是Int類型,而這里??使用rowValue方法構建了枚舉型
        return pointAtVertex(v: Vertex(rawValue: index)!)  //已經(jīng)使用了斷言,這里使用強制解包
    }
}

//測試代碼:
let rect4  = Rectangle(origin: Point(x:0,y:0), size: Size(width: 100, height: 100))
let point1 = rect4.pointAtVertex(v: .TopRight)
print(point1)    //Point(x: 100.0, y: 0.0)
let point2 = rect4.pointAtVertex(v: Rectangle.Vertex.BottomRight)
print(point2)    //Point(x: 100.0, y: 0.0)
let point3 = rect4[2]
print(point3)    //Po

四、擴展系統(tǒng)類庫

4.1.擴展Double

擴展Double,為其添加計算型屬性,提供與距離單位協(xié)作的基本支持。

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 distance1 = 25.4.mm
print("distance1 is \(distance1) meters")    //distance1 is 0.0254 meters
let distance2 = 42.mm + 1.km
print("disatance2 is \( distance2) meters")  //disatance2 is 1000.042 meters

4.2.擴展Int類

擴展Int,為其添加平方、立方、范圍判斷等方法。

extension Int{
    //平方運算
    var square:Int{
        return self * self
    }
    
    //立方運算
    var cube:Int{
        return self * self * self
    }
    
    //判斷整型是否在某個范圍內(nèi)
    func inRange(closedLeft:Int, opendRight:Int) -> Bool{
        return self >= closedLeft && self < opendRight
    }
    
    //通過傳入一個閉包參數(shù),簡單的實現(xiàn)循環(huán)操作
   func  repetitions(task: () -> Void){
        for _ in 0...10{
        //執(zhí)行閉包
            task()
        }
    }
}

 //測試代碼:
var tempNum = 10;
tempNum.square()        //100
tempNum.inRange(closedLeft: 10, opendRight: 100)   //false
tempNum.repetitions {
    print(tempNum)
}
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容