天天看點

21.Swift學習之擴充

擴充

  • 為現有的類、結構體、枚舉類型、協定添加了新功能。擴充和 Objective-C 中的分類類似。
  • 擴充可以:
    • 添加計算屬性;
    • 定義方法;
    • 提供新的構造函數;
    • 使現有的類型遵循某協定
  • Swift中使用

    extension

    關鍵字實作擴充

文法

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

擴充可以使已有的類型遵循一個或多個協定。在這種情況下,協定名的書寫方式與類或結構體完全一樣:

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

擴充計算屬性

  • 擴充可以向已有的類型添加計算執行個體屬性和計算類型屬性。
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 }
}
25.0.km
25.0.m
25.0.cm
25.0.mm
3.0.ft
           

擴充構造函數

  • 擴充可向已有的類型添加新的初始化器
extension CGRect{  
    init(center: CGPoint, size: CGSize) {
        let originX = center.x - size.width * 0.5   
        let originY = center.y - size.height * 0.5    
        self.init(x: originX, y: originY, width: size.width, height: size.height)       
    }    
}
let centerRect = CGRect(center: CGPoint(x: 100.0, y: 100.0), size: CGSize(width: 100.0, height: 100.0))
           

擴充方法

  • 擴充可以為已有的類型添加新的執行個體方法和類型方法。
extension Int {
    func repetitions(task: () -> Void) {
        for _ in 0..<self {
            task()
        }
    }
}


3.repetitions {
    print("Hello!")
}
           

mutating

方法

  • 擴充結構體,如果要修改裡面的值,必須在方法面前加上

    mutating

extension Int {
    mutating func square() {
        self = self * self
    }
}
//必須用變量,因為它的值要被修改
var someInt = 3
someInt.square()
           

class ViewController : UIViewController{
}

extension ViewController : UITableViewDataSource{
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        
        return 10
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        return UITableViewCell()
    }
}
           

面向協定程式設計

針對某個需要實作的功能,可以使用協定定義出接口,然後利用協定擴充提供預設的實作。需要這個功能,隻需要聲明遵守了這個協定即可,遵守某個協定的對象調用協定聲明的方法時,如果類本身沒有提供實作,協定擴充提供的預設實作會被調用。

  • 案例一
protocol Eat {
    func eat()
}

class Person: Eat {
    func eat() {
        print("吃飯了")
    }
}

var p = Person()
p.eat()
           
  • 改進
extension Eatable {
    func eat() {
        print("吃飯了")
    }
}
class Person: Eatable {
}
var p = Person()
p.eat()
           
  • 再次修改
class Person: Eatable {
    
    func eat() {
        print("人要吃飯了")
    }
}

var p = Person()
p.eat()

           
  • 案例二
protocol Coder {
    var haveFun:Bool {get set}
    var ownMoney:Bool {get set}
}


protocol Swifter {
    var codingLevel:Int {get set}
}


struct CoderA : Coder {
    
    var name:String
    var haveFun: Bool
    var ownMoney: Bool
}


struct CoderB : Coder, Swifter {
    
    var name:String
    var haveFun: Bool = true
    var ownMoney: Bool = true
    var codingLevel: Int = 3
}

struct CoderC : Coder, Swifter{
    
    var name:String
    var haveFun: Bool = true
    var ownMoney: Bool = true
    var codingLevel: Int = 5
}
           

可以發現CoderB與CoderC有備援

protocol Coder {
    var haveFun:Bool {get set}
    var ownMoney:Bool {get set}
}


protocol Swifter {
    var codingLevel:Int {get set}
}

//where限定條件
extension Coder where Self:Swifter {
    
    var haveFun:Bool { return true}
    var ownMoney:Bool { return true}
}


struct CoderA : Coder {
    
    var name:String
    var haveFun: Bool
    var ownMoney: Bool
}


struct CoderB : Coder, Swifter {
    
    var name:String
    var haveFun: Bool
    var ownMoney: Bool
    var codingLevel: Int = 3
}

struct CoderC : Coder, Swifter{
    
    var name:String
    var haveFun: Bool
    var ownMoney: Bool
    var codingLevel: Int = 5
}