Swift 拡張

拡張とは、既存のクラス、構造体、または列挙型に新しい機能を追加することです。

拡張は型に新しい機能を追加できますが、既存の機能を書き換えることはできません。

Swiftの拡張では次のことができます:

  • 計算型プロパティと計算型静的プロパティを追加する
  • インスタンスメソッドと型メソッドを定義する
  • 新しいイニシャライザを提供する
  • 添字を定義する
  • 新しいネスト型を定義して使用する
  • 既存の型をあるプロトコルに準拠させる

構文

拡張の宣言ではキーワードを使用しますextension:

extension SomeType {
    // 加到SomeType的新功能写到这里
}

拡張は既存の型を拡張して、1つまたは複数のプロトコルに適合させることができます。構文は次のとおりです:

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

計算型プロパティ

拡張は既存の型に計算型のインスタンスプロパティと計算型の型プロパティを追加できます。

例

次の例では、Int型に5つの計算型インスタンスプロパティを追加して、その機能を拡張しています:

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("加法运算后的值:\(addition)")
    
let subtraction = 120.sub
print("减法运算后的值:\(subtraction)")
    
let multiplication = 39.mul
print("乘法运算后的值:\(multiplication)")
    
let division = 55.div
print("除法运算后的值: \(division)")

let mix = 30.add + 34.sub
print("混合运算结果:\(mix)")

上記のプログラムを実行すると、出力結果は次のようになります:

加法运算后的值:103
减法运算后的值:110
乘法运算后的值:390
除法运算后的值: 11
混合运算结果:154

イニシャライザ

拡張は既存の型に新しいイニシャライザを追加できます。

これにより、他の型を拡張して、独自のカスタム型をイニシャライザのパラメータとして使用したり、その型の元の実装に含まれていない追加の初期化オプションを提供したりできます。

拡張はクラスに新しい便利イニシャライザ init() を追加できますが、クラスに新しい指定イニシャライザやデイニシャライザ deinit() を追加することはできません。

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

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

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


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


let a = sum(num1: 100, num2: 200)
let b = diff(no1: 200, no2: 100)

let getMult = mult(x: a, y: b)
print("getMult sum\(getMult.a.num1, getMult.a.num2)")
print("getMult diff\(getMult.b.no1, getMult.b.no2)")

上記のプログラムを実行すると、出力結果は次のようになります:

getMult sum(100, 200)
getMult diff(200, 100)

メソッド

拡張は既存の型に新しいインスタンスメソッドと型メソッドを追加できます。

次の例では、Int型に topics という名前の新しいインスタンスメソッドを追加しています:

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

4.topics({
   print("扩展模块内")       
})    
    
3.topics({
   print("内型转换模块内")       
})  

上記のプログラムを実行すると、出力結果は次のようになります:

拡張モジュール内
拡張モジュール内
拡張モジュール内
拡張モジュール内
内部型変換モジュール内
内部型変換モジュール内
内部型変換モジュール内

このtopicsメソッドで使用されているのは() -> ()型の単一パラメータで、関数にパラメータがなく戻り値もないことを示しています。

この拡張を定義した後、任意の整数に対してtopicsメソッドを呼び出すことができ、その機能は特定のタスクを複数回実行するというものです:


可変インスタンスメソッド

拡張によって追加されたインスタンスメソッドは、そのインスタンス自体を変更することもできます。

構造体および列挙型では、selfまたはそのプロパティを変更するメソッドは、元の実装の変更メソッドと同様に、そのインスタンスメソッドをmutatingとしてマークする必要があります。

例

次の例では、SwiftのDouble型に square という名前の新しい変更メソッドを追加して、元の値の2乗を計算します:

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)")

上記のプログラムを実行すると、出力結果は次のようになります:

圆的面积为: 34.210935
圆的面积为: 105.68006
圆的面积为: 45464.070735

添字

拡張は既存の型に新しい添字を追加できます。

例

次の例では、Swiftの組み込み型Intに整数型の添字を追加しています。この添字[n]は10進数の数字を返します。

extension Int {
    subscript(multtable: Int) -> Int {
        var powerOf10 = 1
        var index = multtable
        while index > 0 {
            powerOf10 *= 10
            index -= 1
        }
        return (self / powerOf10) % 10
    }
}

print(12[0])     // 输出:2
print(7869[1])   // 输出:6
print(786543[2]) // 输出:5

上記のプログラムを実行すると、出力結果は次のようになります:

2
6
5

ネスト型

拡張は既存のクラス、構造体、および列挙型に新しいネスト型を追加できます:

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])

上記のプログラムを実行すると、出力結果は次のようになります:

 10 
 20 
 30 
 40 
 50 
 50 
その他の拡張