スウィフトジェネリック
スウィフトは、一般的な柔軟を提供し、再利用可能な関数と型を記述することができます。
スウィフト標準ライブラリは、汎用コードによって構築されています。
スウィフト配列や辞書の種類は、一般的なセットです。
あなたはint配列を作成することができます、あなたは文字列の配列を作成することができ、さらにはデータ・アレイは、他のスイフトのいずれかのタイプにすることができます。
次の例は、非ジェネリック関数intスワップ2つの値を交換するために使用されています。
// 定义一个交换两个变量的函数 func exchange(inout a: Int, inout b: Int) { let temp = a a = b b = temp } var numb1 = 100 var numb2 = 200 print("交换前数据: \(numb1) 和 \(numb2)") exchange(&numb1, b: &numb2) print("交换后数据: \(numb1) 和 \(numb2)")
上記プログラム実行出力は、次のとおりです。
交换前数据: 100 和 200 交换后数据: 200 和 100
一般的な機能は、このようなintやStringとして、任意の型にアクセスすることができます。
次の例では、為替スワップ2のIntと文字列値のための一般的な機能です。
func exchange<T>(inout a: T, inout b: T) { let temp = a a = b b = temp } var numb1 = 100 var numb2 = 200 print("交换前数据: \(numb1) 和 \(numb2)") exchange(&numb1, b: &numb2) print("交换后数据: \(numb1) 和 \(numb2)") var str1 = "A" var str2 = "B" print("交换前数据: \(str1) 和 \(str2)") exchange(&str1, b: &str2) print("交换后数据: \(str1) 和 \(str2)")
上記プログラム実行出力は、次のとおりです。
交换前数据: 100 和 200 交换后数据: 200 和 100 交换前数据: A 和 B 交换后数据: B 和 A
代わりに、(そのようなのInt、文字列またはダブルなど)の実際の型の名前のプレースホルダーの型名を使用して、この関数のジェネリック版(通常この場合は文字Tによって表されます)。 プレースホルダのタイプ名はどのタイプTを示唆していなければならないが、それは示唆しているとbは関係なく、Tが何を表すかのタイプの、同じタイプのTでなければなりません。 交換のみ(_:_ :) Tが表す実際の型を決定するために、各コールタイプに渡された関数。
もう一つの違いは、(プレースホルダのタイプ(T)の一般名に続いて、この後者の機能名は角括弧で囲まれていることです
ジェネリック型
スウィフトは、あなた自身のジェネリック型を定義することができます。
カスタムクラス、構造体、および列挙型は、Arrayや辞書の使用などの任意のタイプに適用されます。
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("Swift") print(tos.items) tos.push("泛型") print(tos.items) tos.push("类型参数") print(tos.items) tos.push("类型参数名") print(tos.items) let deletetos = tos.pop()
上記プログラム実行出力は、次のとおりです。
["Swift"] ["Swift", "泛型"] ["Swift", "泛型", "类型参数"] ["Swift", "泛型", "类型参数", "类型参数名"]
拡張ジェネリック型
あなたは(拡張子キーワードを使用して)時間のジェネリック型を拡張する場合は、拡張定義で型パラメータリストを提供する必要はありません。 より便利には、リスト内で宣言プリミティブ型パラメータの型定義が使用中に拡張することができ、元の型からパラメータ名は型パラメータの元の定義への参照として使用されるということです。
例
次の例では、最初の計算という名前の読み取り専用プロパティを追加するために、一般的なTOSの種類を拡張し、それがスタック要素の現在のトップを返し、スタックから削除されることはありません。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("Swift") print(tos.items) tos.push("泛型") print(tos.items) tos.push("类型参数") print(tos.items) tos.push("类型参数名") print(tos.items) // 扩展泛型 TOS 类型 extension TOS { var first: T? { return items.isEmpty ? nil : items[items.count - 1] } } if let first = tos.first { print("栈顶部项:\(first)") }
上記プログラム実行出力は、次のとおりです。
["Swift"] ["Swift", "泛型"] ["Swift", "泛型", "类型参数"] ["Swift", "泛型", "类型参数", "类型参数名"] 栈顶部项:类型参数名
型制約
型制約は、型パラメータが指定されたクラスから継承するか、特定のプロトコルまたは組成物に従わなければならないことを指定します。
タイプ制約構文
あなたは型パラメータチェーンの一部として、コロンで分割された型パラメータ名の後ろ、内型制約を書くことができます。 (構文の同じ一般的なタイプ)は次のように一般的な機能のための制約構文の種類に基づいてこのような行為は、次のとおりです。
func someFunction<T: SomeClass, U: SomeProtocol>(someT: T, someU: U) { // 这里是函数主体 }
例
// 函数可以作用于查找一字符串数组中的某个字符串 func findStringIndex(array: [String], _ valueToFind: String) -> Int? { for (index, value) in array.enumerate() { if value == valueToFind { return index } } return nil } let strings = ["cat", "dog", "llama", "parakeet", "terrapin"] if let foundIndex = findStringIndex(strings, "llama") { print("llama 的下标索引值为 \(foundIndex)") }
上記プログラム実行出力は、次のとおりです。
llama 的下标索引值为 2
関連の種類の例
スウィフトtypealiasキーワードは、関連の種類を設定するために使用しました。
時には1を宣言し、プロトコルを定義するか、定義のプロトコル部分の複数の関連タイプは、非常に便利です。
protocol Container { // 定义了一个ItemType关联类型 typealias ItemType mutating func append(item: ItemType) var count: Int { get } subscript(i: Int) -> ItemType { get } } // 遵循Container协议的泛型TOS类型 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) } var count: Int { return items.count } subscript(i: Int) -> T { return items[i] } } var tos = TOS<String>() tos.push("Swift") print(tos.items) tos.push("泛型") print(tos.items) tos.push("参数类型") print(tos.items) tos.push("类型参数名") print(tos.items)
上記プログラム実行出力は、次のとおりです。
["Swift"] ["Swift", "泛型"] ["Swift", "泛型", "参数类型"] ["Swift", "泛型", "参数类型", "类型参数名"]
どこ文
制約のタイプは、制約のタイプが定義されている一般的な関数やクラスの遵守を確保します。
あなたは、パラメータリストの制約文のパラメータを定義することができます。
どこで文が一つ以上の関連の制約の種類、および続いて背面の型パラメータリスト、続い文を書くことができます(または)1種類以上と、(平等)の関係の間の関連付けタイプの同等。
例
次の例では、コンテナの2つのインスタンスが同じ順序で同じ要素が含まれているかどうかを確認するために使用allItemsMatchという名前の汎用関数を定義しています。
すべての要素が一致することができた場合は、それ以外の場合はfalseで、真のブール値に戻ります。
protocol Container { typealias 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) } 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 { // 检查两个Container的元素个数是否相同 if someContainer.count != anotherContainer.count { return false } // 检查两个Container相应位置的元素彼此是否相等 for i in 0..<someContainer.count { if someContainer[i] != anotherContainer[i] { return false } } // 匹配所有项,返回 true return true } var tos = Stack<String>() tos.push("Swift") print(tos.items) tos.push("泛型") print(tos.items) tos.push("Where 语句") print(tos.items) var eos = ["Swift", "泛型", "Where 语句"] print(eos)
上記プログラム実行出力は、次のとおりです。
["Swift"] ["Swift", "泛型"] ["Swift", "泛型", "Where 语句"] ["Swift", "泛型", "Where 语句"]