Swift 擴(kuò)展

擴(kuò)展就是向一個(gè)已有的類、結(jié)構(gòu)體或枚舉類型添加新功能。

擴(kuò)展可以對(duì)一個(gè)類型添加新的功能,但是不能重寫已有的功能。

Swift 中的擴(kuò)展可以:

  • 添加計(jì)算型屬性和計(jì)算型靜態(tài)屬性
  • 定義實(shí)例方法和類型方法
  • 提供新的構(gòu)造器
  • 定義下標(biāo)
  • 定義和使用新的嵌套類型
  • 使一個(gè)已有類型符合某個(gè)協(xié)議

語法

擴(kuò)展聲明使用關(guān)鍵字 extension

extension SomeType {
    // 加到SomeType的新功能寫到這里
}

一個(gè)擴(kuò)展可以擴(kuò)展一個(gè)已有類型,使其能夠適配一個(gè)或多個(gè)協(xié)議,語法格式如下:

extension SomeType: SomeProtocol, AnotherProctocol {
    // 協(xié)議實(shí)現(xiàn)寫到這里
}

計(jì)算型屬性

擴(kuò)展可以向已有類型添加計(jì)算型實(shí)例屬性和計(jì)算型類型屬性。

實(shí)例

下面的例子向 Int 類型添加了 5 個(gè)計(jì)算型實(shí)例屬性并擴(kuò)展其功能:

extension Int {
   var add: Int {return self + 100 }
   var sub: Int { return self - 10 }
   var mul: Int { return self * 10 }
   var div: Int { return self / 5 }
}
    
let addition = 3.add
print("加法運(yùn)算后的值:\(addition)")
    
let subtraction = 120.sub
print("減法運(yùn)算后的值:\(subtraction)")
    
let multiplication = 39.mul
print("乘法運(yùn)算后的值:\(multiplication)")
    
let division = 55.div
print("除法運(yùn)算后的值: \(division)")

let mix = 30.add + 34.sub
print("混合運(yùn)算結(jié)果:\(mix)")

以上程序執(zhí)行輸出結(jié)果為:

加法運(yùn)算后的值:103
減法運(yùn)算后的值:110
乘法運(yùn)算后的值:390
除法運(yùn)算后的值: 11
混合運(yùn)算結(jié)果:154

構(gòu)造器

擴(kuò)展可以向已有類型添加新的構(gòu)造器。

這可以讓你擴(kuò)展其它類型,將你自己的定制類型作為構(gòu)造器參數(shù),或者提供該類型的原始實(shí)現(xiàn)中沒有包含的額外初始化選項(xiàng)。

擴(kuò)展可以向類中添加新的便利構(gòu)造器 init(),但是它們不能向類中添加新的指定構(gòu)造器或析構(gòu)函數(shù) deinit() 。

struct sum {
    var num1 = 100, num2 = 200
}

struct diff {
    var no1 = 200, no2 = 100
}

struct mult {
    var a = sum()
    var b = diff()
}

let calc = mult()
print ("mult 模塊內(nèi) \(calc.a.num1, calc.a.num2)")
print("mult 模塊內(nèi) \(calc.b.no1, calc.b.no2)")

let memcalc = mult(a: sum(num1: 300, num2: 500),b: diff(no1: 300, no2: 100))

print("mult 模塊內(nèi) \(memcalc.a.num1, memcalc.a.num2)")
print("mult 模塊內(nèi) \(memcalc.b.no1, memcalc.b.no2)")

extension mult {
    init(x: sum, y: diff) {
        _ = x.num1 + x.num2
        _ = y.no1 + y.no2
    }
}


let a = sum(num1: 100, num2: 200)
print("Sum 模塊內(nèi):\( a.num1, a.num2)")


let b = diff(no1: 200, no2: 100)
print("Diff 模塊內(nèi): \(b.no1, b.no2)")

以上程序執(zhí)行輸出結(jié)果為:

mult 模塊內(nèi) (100, 200)
mult 模塊內(nèi) (200, 100)
mult 模塊內(nèi) (300, 500)
mult 模塊內(nèi) (300, 100)
Sum 模塊內(nèi):(100, 200)
Diff 模塊內(nèi): (200, 100)

方法

擴(kuò)展可以向已有類型添加新的實(shí)例方法和類型方法。

下面的例子向Int類型添加一個(gè)名為 topics 的新實(shí)例方法:

extension Int {
   func topics(summation: () -> ()) {
      for _ in 0..<self {
         summation() 
      }
   }
}  

4.topics({
   print("擴(kuò)展模塊內(nèi)")       
})    
    
3.topics({
   print("內(nèi)型轉(zhuǎn)換模塊內(nèi)")       
})  

以上程序執(zhí)行輸出結(jié)果為:

擴(kuò)展模塊內(nèi)
擴(kuò)展模塊內(nèi)
擴(kuò)展模塊內(nèi)
擴(kuò)展模塊內(nèi)
內(nèi)型轉(zhuǎn)換模塊內(nèi)
內(nèi)型轉(zhuǎn)換模塊內(nèi)
內(nèi)型轉(zhuǎn)換模塊內(nèi)

這個(gè)topics方法使用了一個(gè)() -> ()類型的單參數(shù),表明函數(shù)沒有參數(shù)而且沒有返回值。

定義該擴(kuò)展之后,你就可以對(duì)任意整數(shù)調(diào)用 topics 方法,實(shí)現(xiàn)的功能則是多次執(zhí)行某任務(wù):


可變實(shí)例方法

通過擴(kuò)展添加的實(shí)例方法也可以修改該實(shí)例本身。

結(jié)構(gòu)體和枚舉類型中修改self或其屬性的方法必須將該實(shí)例方法標(biāo)注為mutating,正如來自原始實(shí)現(xiàn)的修改方法一樣。

實(shí)例

下面的例子向 Swift 的 Double 類型添加了一個(gè)新的名為 square 的修改方法,來實(shí)現(xiàn)一個(gè)原始值的平方計(jì)算:

extension Double {
   mutating func square() {
      let pi = 3.1415
      self = pi * self * self
   }
}

var Trial1 = 3.3
Trial1.square()
print("圓的面積為: \(Trial1)")


var Trial2 = 5.8
Trial2.square()
print("圓的面積為: \(Trial2)")


var Trial3 = 120.3
Trial3.square()
print("圓的面積為: \(Trial3)")

以上程序執(zhí)行輸出結(jié)果為:

圓的面積為: 34.210935
圓的面積為: 105.68006
圓的面積為: 45464.070735

下標(biāo)

擴(kuò)展可以向一個(gè)已有類型添加新下標(biāo)。

實(shí)例

以下例子向 Swift 內(nèi)建類型Int添加了一個(gè)整型下標(biāo)。該下標(biāo)[n]返回十進(jìn)制數(shù)字

extension Int {
   subscript(var multtable: Int) -> Int {
      var no1 = 1
      while multtable > 0 {
         no1 *= 10
         --multtable
      }
      return (self / no1) % 10
   }
}
    
print(12[0])
print(7869[1])
print(786543[2])

以上程序執(zhí)行輸出結(jié)果為:

2
6
5

嵌套類型

擴(kuò)展可以向已有的類、結(jié)構(gòu)體和枚舉添加新的嵌套類型:

extension Int {
   enum calc
   {
      case add
      case sub
      case mult
      case div
      case anything
   }

   var print: calc {
      switch self
      {
         case 0:
            return .add
         case 1:
            return .sub
         case 2:
            return .mult
         case 3:
            return .div
         default:
            return .anything
       }
   }
}

func result(numb: [Int]) {
   for i in numb {
      switch i.print {
         case .add:
            print(" 10 ")
          case .sub:
            print(" 20 ")
         case .mult:
         print(" 30 ")
         case .div:
         print(" 40 ")
         default:
         print(" 50 ")

      }
   }
}

result([0, 1, 2, 3, 4, 7])

以上程序執(zhí)行輸出結(jié)果為:

 10 
 20 
 30 
 40 
 50 
 50