Swift 扩展


扩展就是向一个已有的类、结构体或枚举类型添加新功能。

扩展可以对一个类型添加新的功能,但是不能重写已有的功能。

Swift 中的扩展可以:

  • 添加计算型属性和计算型静态属性
  • 定义实例方法和类型方法
  • 提供新的构造器
  • 定义下标
  • 定义和使用新的嵌套类型
  • 使一个已有类型符合某个协议

语法

扩展声明使用关键字 extension

  1. extension SomeType {
  2. // 加到SomeType的新功能写到这里
  3. }

一个扩展可以扩展一个已有类型,使其能够适配一个或多个协议,语法格式如下:

  1. extension SomeType: SomeProtocol, AnotherProctocol {
  2. // 协议实现写到这里
  3. }

计算型属性

扩展可以向已有类型添加计算型实例属性和计算型类型属性。

实例

下面的例子向 Int 类型添加了 5 个计算型实例属性并扩展其功能:

  1. extension Int {
  2. var add: Int {return self + 100 }
  3. var sub: Int { return self - 10 }
  4. var mul: Int { return self * 10 }
  5. var div: Int { return self / 5 }
  6. }
  7. let addition = 3.add
  8. print("加法运算后的值:\(addition)")
  9. let subtraction = 120.sub
  10. print("减法运算后的值:\(subtraction)")
  11. let multiplication = 39.mul
  12. print("乘法运算后的值:\(multiplication)")
  13. let division = 55.div
  14. print("除法运算后的值: \(division)")
  15.  
  16. let mix = 30.add + 34.sub
  17. print("混合运算结果:\(mix)")

以上程序执行输出结果为:

  1. 加法运算后的值:103
  2. 减法运算后的值:110
  3. 乘法运算后的值:390
  4. 除法运算后的值: 11
  5. 混合运算结果:154

构造器

扩展可以向已有类型添加新的构造器。

这可以让你扩展其它类型,将你自己的定制类型作为构造器参数,或者提供该类型的原始实现中没有包含的额外初始化选项。

扩展可以向类中添加新的便利构造器 init(),但是它们不能向类中添加新的指定构造器或析构函数 deinit() 。

  1. struct sum {
  2. var num1 = 100, num2 = 200
  3. }
  4.  
  5. struct diff {
  6. var no1 = 200, no2 = 100
  7. }
  8.  
  9. struct mult {
  10. var a = sum()
  11. var b = diff()
  12. }
  13.  
  14.  
  15. extension mult {
  16. init(x: sum, y: diff) {
  17. _ = x.num1 + x.num2
  18. _ = y.no1 + y.no2
  19. }
  20. }
  21.  
  22.  
  23. let a = sum(num1: 100, num2: 200)
  24. let b = diff(no1: 200, no2: 100)
  25.  
  26. let getMult = mult(x: a, y: b)
  27. print("getMult sum\(getMult.a.num1, getMult.a.num2)")
  28. print("getMult diff\(getMult.b.no1, getMult.b.no2)")

以上程序执行输出结果为:

  1. getMult sum(100, 200)
  2. getMult diff(200, 100)

方法

扩展可以向已有类型添加新的实例方法和类型方法。

下面的例子向Int类型添加一个名为 topics 的新实例方法:

  1. extension Int {
  2. func topics(summation: () -> ()) {
  3. for _ in 0..<self {
  4. summation()
  5. }
  6. }
  7. }
  8.  
  9. 4.topics({
  10. print("扩展模块内")
  11. })
  12. 3.topics({
  13. print("内型转换模块内")
  14. })

以上程序执行输出结果为:

  1. 扩展模块内
  2. 扩展模块内
  3. 扩展模块内
  4. 扩展模块内
  5. 内型转换模块内
  6. 内型转换模块内
  7. 内型转换模块内

这个topics方法使用了一个() -> ()类型的单参数,表明函数没有参数而且没有返回值。

定义该扩展之后,你就可以对任意整数调用 topics 方法,实现的功能则是多次执行某任务:

可变实例方法

通过扩展添加的实例方法也可以修改该实例本身。

结构体和枚举类型中修改self或其属性的方法必须将该实例方法标注为mutating,正如来自原始实现的修改方法一样。

实例

下面的例子向 Swift 的 Double 类型添加了一个新的名为 square 的修改方法,来实现一个原始值的平方计算:

  1. extension Double {
  2. mutating func square() {
  3. let pi = 3.1415
  4. self = pi * self * self
  5. }
  6. }
  7.  
  8. var Trial1 = 3.3
  9. Trial1.square()
  10. print("圆的面积为: \(Trial1)")
  11.  
  12.  
  13. var Trial2 = 5.8
  14. Trial2.square()
  15. print("圆的面积为: \(Trial2)")
  16.  
  17.  
  18. var Trial3 = 120.3
  19. Trial3.square()
  20. print("圆的面积为: \(Trial3)")

以上程序执行输出结果为:

  1. 圆的面积为: 34.210935
  2. 圆的面积为: 105.68006
  3. 圆的面积为: 45464.070735

下标

扩展可以向一个已有类型添加新下标。

实例

以下例子向 Swift 内建类型Int添加了一个整型下标。该下标[n]返回十进制数字

  1. extension Int {
  2. subscript(var multtable: Int) -> Int {
  3. var no1 = 1
  4. while multtable > 0 {
  5. no1 *= 10
  6. --multtable
  7. }
  8. return (self / no1) % 10
  9. }
  10. }
  11. print(12[0])
  12. print(7869[1])
  13. print(786543[2])

以上程序执行输出结果为:

  1. 2
  2. 6
  3. 5

嵌套类型

扩展可以向已有的类、结构体和枚举添加新的嵌套类型:

  1. extension Int {
  2. enum calc
  3. {
  4. case add
  5. case sub
  6. case mult
  7. case div
  8. case anything
  9. }
  10.  
  11. var print: calc {
  12. switch self
  13. {
  14. case 0:
  15. return .add
  16. case 1:
  17. return .sub
  18. case 2:
  19. return .mult
  20. case 3:
  21. return .div
  22. default:
  23. return .anything
  24. }
  25. }
  26. }
  27.  
  28. func result(numb: [Int]) {
  29. for i in numb {
  30. switch i.print {
  31. case .add:
  32. print(" 10 ")
  33. case .sub:
  34. print(" 20 ")
  35. case .mult:
  36. print(" 30 ")
  37. case .div:
  38. print(" 40 ")
  39. default:
  40. print(" 50 ")
  41.  
  42. }
  43. }
  44. }
  45.  
  46. result([0, 1, 2, 3, 4, 7])

以上程序执行输出结果为:

  1. 10
  2. 20
  3. 30
  4. 40
  5. 50
  6. 50