运用扩展能够给现已存在的类添加新的办法,尤其是你对某个类没有控制权的时分。扩展非常有用,尤其是帮你安排你的代码的时分。

什么是扩展

Swift的类、结构体、枚举或者协议都能够运用扩展来添加新的办法。即便这些类型不在你的控制范围内。如:

class Airplane {
 var altitude: Double = 0
 func setAltitude(feet: Double) {
  altitude = feet
 }
}

有人想运用单位英尺来描绘altitude,有人想用单位米。假如这段代码你无法修正,你也不想承继这个类你就能够新建一个扩展。比方:

extension Airplane {
 func setAltitude(meter: Double) {
  altitude = meter * 3.28084
 }
}

这样就能够在一个Airplane的目标上运用办法setAltitude了。如:

let boeing = Airplane()
boeing.setAltitude(meter: 12000)  
print(boeing.altitude) // Output: 39370.08

扩展在编译的时分,扩展都会和原来的类整合到一同。

所以Swift的扩展能够:

  • 添加办法和核算特色
  • 供给新的初始化办法
  • 运用subscript()界说下标
  • 添加嵌套类型
  • 完成某些协议,这很有用
  • 运用协议扩展给协议添加默许完成

扩展尽管好用,可是无法改变一个类(结构体)的基本结构。只能用来添加功用,而不是替换。因而不能给一个类型添加新的特色,比方下面的比方这样是不行的:

extension Airplane {
    var speed: Int = 0
}

为什么不能够呢。由于给一个类型添加特色破坏了类型的结构。而且原本就能够经过承继的方法来更改类型的结构。

扩展的别的一个优点是,它能够协助安排好你的代码等各种实践可操作性的特色。比方:

  • 别离、安排代码
  • 能够运用协议共同性
  • 命名空间常量
  • 添加办法、特色
  • 扩展协议

咱们一条一条来距离阐明

别离、安排代码

运用扩展能够把一个类的代码别离,安排成不同的部分。比方在这通用类的部分只保留特色,在扩展里面添加办法。

比方:

class Airplane
{
 var speed: Double = 0
 var altitude: Double = 0
 var bearing: Double = 0
}

之后运用不同的扩展。首要:

extension Airplane
{
 func changeAltitude(altitude: Double) {
  self.altitude = altitude
 }

 func changeBearing(degrees: Double) {
  self.bearing = degrees
 }
}

然后让飞机能够起飞和着陆:

extension Airplane
{
 func takeOff()
 {
  // Do take-off magic…
 }
 func land()
 {
  // Please stow hand luggage and move your seat to an upright position…
 }
}

每个扩展能够有他们独立的文件,假如一个文件开始膨胀的时分,最好把他们依照功用放到不同的当地。比方,你新添加了一个view controller。它有两个主要功用,你能够把这两个功用放在两个扩展里。那个view controller能够持续当做一个完好的来运用。

运用协议共同性

你能够运用扩展让原来的类型恪守某一个协议。比方:

class DetailViewController: UIViewController
{  
    // Do view controller magic…  
}
extension DetailViewController: CLLocationManagerDelegate  
{  
    // Put all location code in here…  
}

在上面的代码里,DetailViewController恪守了CLLocationManagerDelegate协议,你能够放心的在这个扩展里添加代码了。

有一点要记住。扩展可不是你不合理的规划代码的接口。一个巨大的类分割成十个扩展仍是一个巨大的类。合理的规划才是重中之重!

命名空间常量和嵌套类型

运用扩展能够添加静态常量和嵌套类型。

例如:

extension Notification.Name {
    static let statusUpdated = Notification.Name(“status_updated”)  
}

以上的代码扩展了Notification.Name,添加了statusUpdated常量。能够这样运用:NotificationCenter.default.post(name: .statusUpdated, object: nil)

post(name:object:)办法需要Notification.Name的一个值作为第一个参数,这儿就运用了刚刚添加的statusUpdated

添加嵌套类型:

extension UserDefaults
{  
    struct Keys  
    {  
        static let useSync = “use_sync”  
        static let lastSync = “last_sync”  
    }  
}

能够这样运用:

UserDefaults.default.set(true, forKey: UserDefaults.Keys.useSync)

这样有两个优点:

  • Keys嵌套类型只会在UserDefaults类型里能够用。你不必忧虑会有什么类型的重名问题。这样的操作也很类似于其他语言里的类级别命名空间。
  • UserDefaults里运用的时分,假如直接输入use_sync常量的话也不必忧虑系统提示会提示到什么其他当地界说的常量。

扩展核算特色和办法

这儿举一个栗子。在Swift 4.2的时分数组没有shuffled()办法。 承继数组能够添加这么一个办法,也能够运用大局办法处理数组。可是运用扩展能够直接给数组添加这个办法了。如:

extension Array
{  
    func shuffled() {  
        // Shuffle array items and return shuffled array  
    }  
}

这样shuffled()办法就能够在恣意的数组上运用了。

另一个很有协助的比方:

class Circle {
    var radius: Double = 0  
}
extension Circle  
{  
    var circumference:Double {  
        return radius * .pi * 2  
    }  
}

上面的代码首要界说了一个Circle类,然后经过扩展给这个类添加了一个核算特色circumference。能够这样运用这个特色:

let circle = Circle()
circle.radius = 10  
print(circle.circumference) // Output: 62.83185307179586

扩展协议

不同于协议共同(如上),协议扩展能够直接对一个协议进行扩展。能够在扩展协议的时分添协议的默许完成。

例如:

protocol Edible {
    func eat()  
}

协议Edible里界说了办法eat,每个恪守这个协议的类型都要完成eat()办法,例如:

class Fish: Edible
{  
    func eat() {  
        print(“**CHOMP** **CRUNCH** Eating the fish”)  
    }  
}

下面来经过扩展Edible协议给它添加一个默许完成:

extension Edible
{  
    func eat() {  
        print(“Eating the thing”)  
    }  
}

这个扩展扩展的是Edible,不是Fish类。现在任何完成了协议Edible的类型都能够运用eat办法的默许完成了,例如:

class Apple: Edible {
    // Do nothing…  
}
let apple = Apple()  
apple.eat() // Output: Eating the thing…

在上例中就能够直接调用eat()办法了。尽管Apple类并没有供给eat办法的完成。

最后

扩展添加了编写代码的方法,你能够给一个你无法修正的类添加办法、核算特色。你也能够运用扩展来更好的安排代码。用着着实不错!