Swift入門チュートリアル19-汎用


オリジナルBlog、転載は出典を明記してください
blog.csdn.net/hello_hwc
一般的な定義
C++と同様に,汎用型は任意のタイプに適した再利用可能なコードを定義し,抽象的な方法でコードを実現した.SwiftのArrayとDictionaryは、Stringタイプの変数を保存したり、Intタイプを保存したりすることができるため、汎用で実現されています.
例を挙げる
func swapTwoInts(inout a: Int, inout b: Int) {
    let temporaryA = a
    a=b
    b = temporaryA
}
func swapTwoStrings(inout a: String, inout b: String) {
        let temporaryA = a
        a=b
        b = temporaryA
}
func swapTwoDoubles(inout a: Double, inout b: Double) {
        let temporaryA = a
        a=b
        b = temporaryA
}
これは同じ関数構造で2つのタイプを交換するために使用されますが、汎用でなければ、各タイプに対応する関数を定義しなければなりません.煩わしい.
汎用型を使用すると、このように定義するだけです.
func swapTwoValues<T>(inout a: T, inout b: T) { let temporaryA = a
    a=b
    b = temporaryA
}

ここでのTは占有タイプであり,コンパイラに教えるものであり,これは汎用的なタイプであり,実際の演算では具体的なタイプが置き換えられる.占有タイプはパラメータとしても、戻り値としても使用できます.もちろん、のように複数定義してもよい
注意:Swiftはタイプが安全な言語で、コンパイラはタイプチェックを行い、タイプが一致しないとエラーが発生します.
二種類の拘束
汎用定義では、タイプコンストレイントが重要です.例えば、1つの汎用型を定義して1組のデータを並べ替えると、このグループのデータは必ず比較(より大きく、等しい、より小さい)することができ、そうでなければ、1組のデータにはIntもあれば、Stringもあり、IntとStringが並べ替えられ、明らかに合理的なルールはありません.
汎用コンストレイントは、このタイプがクラスを継承するか、プロトコルを実装する必要があることを示します.
文法は次のとおりです.
func someFunction<T: SomeClass, U: SomeProtocol>(someT: T, someU: U) { // function body goes here
}

次に、タイプコンストレイントを使用して汎用を定義する例を実装します.
func findIndex<T: Equatable>(array: T[], valueToFind: T) -> Int? {
    for (index, value) in enumerate(array) {
            if value == valueToFind {
                return index
            }
    }
    return nil
}
ここでは、配列内で指定されたデータを検索する関数を汎用的に定義し、このタイプTは==演算子をサポートすることが明らかである.Equatableはシステムが提供するプロトコルであり、このプロトコルのタイプに従って==演算子を使用することができる.
3つの関連タイプ
2では、システムが提供するEquatableを使用していますが、似たようなプロトコルをどのようにカスタマイズしますか?
関連タイプを使用します.構文は、プロトコルでtypealiseキーワードを使用して関連タイプを定義します.
例を挙げる
protocol Container {
typealias ItemType
mutating func append(item: ItemType) 
var count: Int { get }
subscript(i: Int) -> ItemType { get }
}
ここでは、関連タイプ、ItemTypeを定義し、プロトコルにとって、このプロトコルに従う任意の構造体は、2つのメソッド(append,count)の下付きスクリプトを実装する必要があります.一方,ItemTypeの具体的なタイプはプロトコルに従うクラスによって決定される.たとえば
struct IntStack: Container {
// IntStack

4 Where文
Where文は、関連付けタイプをさらに制約します.1つの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
            }
        }
        return true
}

ここでは4つのコンストレイントを定義します
1.C 1はContainerプロトコルに従う必要がある
2.C 2はContainerプロトコルに従う必要がある
3.C 01とC 2のItemTypeは一致する
4.C 1のItemTypeはEquatableプロトコルに従う