Type Constraints で説明されているように、ジェネリックな関数や型に関連する型パラメータに、型制約で要件を定義することができます。
また、関連型に要件を定義することが有益な場合もあります。これには、型パラメータリストの一部として where 節を定義します。関連型が特定のプロトコルに準拠することや、特定の型パラメータと関連型が同じであることを、where 節によって要求することができます。型パラメータのリストの直後に where
キーワードを置き、関連型や型と関連型の相等関係に対する制約を続けて where 節を記述します。
下の例では、2 つの Container
インスタンスに同じアイテムが同じ順序で含まれているかをチェックするジェネリック関数 allItemsMatch
を定義しています。この関数は、すべてのアイテムが一致する場合に true
のブール値を、そうでない場合には false
の値を返します。
チェックされる 2 つのコンテナは同じ型のコンテナである必要は(あっても構わないですが)ありませんが、同じ型のアイテムを保持する必要があります。この要件は、型制約と where 節の組み合わせで表現されています。
func allItemsMatch<
C1: Container, C2: Container
where C1.ItemType == C2.ItemType, C1.ItemType: Equatable>
(someContainer: C1, _ anotherContainer: C2) -> Bool {
// 両コンテナに含まれるアイテム数が同じであることを確認
if someContainer.count != anotherContainer.count {
return false
}
// アイテムの各ペアが同等であることを確認
for i in 0..<someContainer.count {
if someContainer[i] != anotherContainer[i] {
return false
}
}
// すべてのアイテムが一致しているため true を返す
return true
}
この関数は someContainer
と anotherContainer
の 2 つの引数を取ります。引数 someContainer
は C1
型で、引数 anotherContainer
は C2
型です。C1
と C2
は共に、関数が呼び出されたときに決まるコンテナ型の型パラメータです。
関数の型パラメータリストは、2 つの型パラメータに次の要件を要求しています。
C1
はContainer
プロトコルに準拠すること (C1: Container
)C2
はContainer
プロトコルに準拠すること (C2: Container
)C1
のItemType
はC2
のItemType
と同じであること (C1.ItemType == C2.ItemType
)C1
のItemType
はEquatable
プロトコルに準拠すること (C1.ItemType: Equatable
)
3 つ目と 4 つ目の要件は where 節の一部として定義されていて、関数の型パラメータリストの一部として where
キーワードの後に記述されています。
これらの要件は、次のような意味になります。
someContainer
はC1
型のコンテナであるanotherContainer
はC2
型のコンテナであるsomeContainer
とanotherContainer
には同じ型のアイテムが含まれるsomeContainer
のアイテムが互いに異なっているかを確認するために!=
(等しくない)演算子でチェックすることができる
3 つ目と 4 つ目の要件の組み合わせで、anotherContainer
にあるアイテムについても、someContainer
にあるアイテムとまったく同じ型であるため、!=
演算子でチェックできることを意味します。
これらの要件によって、2 つのコンテナが異なるコンテナ型であったとしても、allItemsMatch(_:_:)
関数で比較できるようになっています。
allItemsMatch(_:_:)
関数は、両コンテナに含まれるアイテム数が同じであることをはじめにチェックしています。アイテム数が異なる場合、一致することはありえず、関数は false
を返します。
このチェック後、関数は for
–in
ループと半開範囲演算子 (..<
) で someContainer
にあるすべてのアイテムを繰り返し処理します。各アイテムに対して、someContainer
のアイテムとそれに対応する anotherContainer
のアイテムが等しくないかどうかをチェックします。2 つのアイテムが等しくない場合には 2 つのコンテナは一致せず、関数は false
を返します。
誤った組み合わせを見つけることなくループが終了した場合、2 つのコンテナは一致し、関数は true
を返します。
次は、allItemsMatch(_:_:)
関数がどのように動作するかを示しています。
var stackOfStrings = Stack<String>()
stackOfStrings.push("uno")
stackOfStrings.push("dos")
stackOfStrings.push("tres")
var arrayOfStrings = ["uno", "dos", "tres"]
if allItemsMatch(stackOfStrings, arrayOfStrings) {
print("All items match.")
} else {
print("Not all items match.")
}
// "All items match." と出力
この例は String
値を保管する Stack
インスタンスを生成し、スタックに 3 つの文字列をプッシュしています。また、スタックと同じ 3 つの文字列を含む配列リテラルで初期化された Array
インスタンスを生成しています。スタックと配列の型は異なりますが、共に Container
プロトコルに準拠し、同じ型の値が含まれています。そのため、これらの 2 つのコンテナを引数として allItemsMatch(_:_:)
関数を呼び出すことができます。上の例では、allItemsMatch(_:_:)
関数が 2 つのコンテナにあるアイテムがすべて一致することを正しく報告しています。
Portions of this page are translations based on work created and shared by Apple and used according to terms described in the Creative Commons Attribution 4.0 International License.