Swift-generics

提供:Dev Guides
移動先:案内検索

Swift-ジェネリック

Swift 4言語は、柔軟で再利用可能な関数と型を記述する「汎用」機能を提供します。 ジェネリックは、重複を避けて抽象化を提供するために使用されます。 Swift 4標準ライブラリは、ジェネリックコードで構築されています。 Swift 4sの「配列」および「辞書」タイプは汎用コレクションに属します。 配列と辞書の助けを借りて、配列は「Int」値と「String」値またはその他の型を保持するように定義されています。

func exchange(a: inout Int, b: inout Int) {
   let temp = a
   a = b
   b = temp
}

var numb1 = 100
var numb2 = 200

print("Before Swapping values are: \(numb1) and \(numb2)")
exchange(a: &numb1, b: &numb2)
print("After Swapping values are: \(numb1) and \(numb2)")

プレイグラウンドを使用して上記のプログラムを実行すると、次の結果が得られます-

Before Swapping values are: 100 and 200
After Swapping values are: 200 and 100

汎用関数:型パラメーター

ジェネリック関数を使用して、「Int」や「String」などのデータ型にアクセスできます。

func exchange<T>(a: inout T, b: inout T) {
   let temp = a
   a = b
   b = temp
}
var numb1 = 100
var numb2 = 200

print("Before Swapping Int values are: \(numb1) and \(numb2)")
exchange(a: &numb1, b: &numb2)
print("After Swapping Int values are: \(numb1) and \(numb2)")

var str1 = "Generics"
var str2 = "Functions"

print("Before Swapping String values are: \(str1) and \(str2)")
exchange(a: &str1, b: &str2)
print("After Swapping String values are: \(str1) and \(str2)")

プレイグラウンドを使用して上記のプログラムを実行すると、次の結果が得られます-

Before Swapping Int values are: 100 and 200
After Swapping Int values are: 200 and 100
Before Swapping String values are: Generics and Functions
After Swapping String values are: Functions and Generics

関数exchange()は、上記のプログラムで説明されている値を交換するために使用され、<T>は型パラメーターとして使用されます。 初めて、関数exchange()が呼び出されて 'Int’値が返され、関数exchange()の2回目の呼び出しで 'String’値が返されます。 カンマで区切られた山括弧内に複数のパラメータタイプを含めることができます。

型パラメーターは、それが保持する型パラメーターの目的を知るためにユーザー定義として命名されます。 Swift 4は、<T>をジェネリック型パラメーター名として提供します。 ただし、配列や辞書などの型パラメーターは、それらが型「辞書」に属していることを識別するキー、値として指定することもできます。

struct TOS<T> {
   var items = [T]()
   mutating func push(item: T) {
      items.append(item)
   }
   mutating func pop() -> T {
      return items.removeLast()
   }
}

var tos = TOS<String>()
tos.push(item: "Swift 4")
print(tos.items)

tos.push(item: "Generics")
print(tos.items)

tos.push(item: "Type Parameters")
print(tos.items)

tos.push(item: "Naming Type Parameters")
print(tos.items)

let deletetos = tos.pop()

プレイグラウンドを使用して上記のプログラムを実行すると、次の結果が得られます-

[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Type Parameters]
[Swift 4, Generics, Type Parameters, Naming Type Parameters]

ジェネリック型の拡張

スタックプロパティを拡張してアイテムの上部を知ることは、 'extension’キーワードに含まれています。

struct TOS<T> {
   var items = [T]()
   mutating func push(item: T) {
      items.append(item)
   }
   mutating func pop() -> T {
      return items.removeLast()
   }
}
var tos = TOS<String>()
tos.push(item: "Swift 4")
print(tos.items)

tos.push(item: "Generics")
print(tos.items)

tos.push(item: "Type Parameters")
print(tos.items)

tos.push(item: "Naming Type Parameters")
print(tos.items)

extension TOS {
   var first: T? {
      return items.isEmpty ? nil : items[items.count - 1]
   }
}
if let first = tos.first {
   print("The top item on the stack is \(first).")
}

プレイグラウンドを使用して上記のプログラムを実行すると、次の結果が得られます-

["Swift 4"]
["Swift 4", "Generics"]
["Swift 4", "Generics", "Type Parameters"]
["Swift 4", "Generics", "Type Parameters", "Naming Type Parameters"]
The top item on the stack is Naming Type Parameters.

型の制約

Swift 4言語では、「型制約」を使用して、型パラメーターが特定のクラスを継承するかどうかを指定したり、プロトコル適合規格を保証したりできます。

func exchange<T>(a: inout T, b: inout T) {
   let temp = a
   a = b
   b = temp
}
var numb1 = 100
var numb2 = 200

print("Before Swapping Int values are: \(numb1) and \(numb2)")
exchange(a: &numb1, b: &numb2)
print("After Swapping Int values are: \(numb1) and \(numb2)")

var str1 = "Generics"
var str2 = "Functions"

print("Before Swapping String values are: \(str1) and \(str2)")
exchange(a: &str1, b: &str2)
print("After Swapping String values are: \(str1) and \(str2)")

プレイグラウンドを使用して上記のプログラムを実行すると、次の結果が得られます-

Before Swapping Int values are: 100 and 200
After Swapping Int values are: 200 and 100
Before Swapping String values are: Generics and Functions
After Swapping String values are: Functions and Generics

関連するタイプ

Swift 4では、キーワード 'associatedtype’によってプロトコル定義内で関連型を宣言できます。

protocol Container {
   associatedtype ItemType
   mutating func append(item: ItemType)
   var count: Int { get }
   subscript(i: Int) -> ItemType { get }
}
struct TOS<T>: Container {
  //original Stack<T> implementation
   var items = [T]()
   mutating func push(item: T) {
      items.append(item)
   }
   mutating func pop() -> T {
      return items.removeLast()
   }

  //conformance to the Container protocol
   mutating func append(item: T) {
      self.push(item: item)
   }
   var count: Int {
      return items.count
   }
   subscript(i: Int) -> T {
      return items[i]
   }
}
var tos = TOS<String>()
tos.push(item: "Swift 4")
print(tos.items)

tos.push(item: "Generics")
print(tos.items)

tos.push(item: "Type Parameters")
print(tos.items)

tos.push(item: "Naming Type Parameters")
print(tos.items)

プレイグラウンドを使用して上記のプログラムを実行すると、次の結果が得られます-

[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Type Parameters]
[Swift 4, Generics, Type Parameters, Naming Type Parameters]

Where句

型制約により、ユーザーは汎用関数または型に関連付けられた型パラメーターの要件を定義できます。 関連する型の要件を定義するために、「where」句は型パラメーターリストの一部として宣言されます。 'where’キーワードは、型パラメーターのリストの直後に配置され、その後に関連する型の制約、型と関連する型の間の等価関係が続きます。

protocol Container {
   associatedtype ItemType
   mutating func append(item: ItemType)
   var count: Int { get }
   subscript(i: Int) -> ItemType { get }
}
struct Stack<T>: Container {
  //original Stack<T> implementation
   var items = [T]()
   mutating func push(item: T) {
      items.append(item)
   }
   mutating func pop() -> T {
      return items.removeLast()
   }

  //conformance to the Container protocol
   mutating func append(item: T) {
      self.push(item: item)
   }
   var count: Int {
      return items.count
   }
   subscript(i: Int) -> T {
      return items[i]
   }
}
func allItemsMatch<
C1: Container, C2: Container
where C1.ItemType == C2.ItemType, C1.ItemType: Equatable>
(someContainer: C1, anotherContainer: C2) -> Bool {
  //check that both containers contain the same number of items
   if someContainer.count != anotherContainer.count {
      return false
   }

  //check each pair of items to see if they are equivalent
   for i in 0..<someContainer.count {
      if someContainer[i] != anotherContainer[i] {
         return false
      }
   }
  //all items match, so return true
   return true
}
var tos = Stack<String>()

tos.push(item: "Swift 4")
print(tos.items)

tos.push(item: "Generics")
print(tos.items)

tos.push(item: "Where Clause")
print(tos.items)

var eos = ["Swift 4", "Generics", "Where Clause"]
print(eos)

プレイグラウンドを使用して上記のプログラムを実行すると、次の結果が得られます-

[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Where Clause]
[Swift 4, Generics, Where Clause]