3

Array クラスの Min および Max 拡張機能を作成することで、Swift の Generics の理解を深めようとしています (C# の Min および Max Extension メソッドに似ています)。これを行うためのより良い方法があるかもしれませんが、私が言ったように、ジェネリックを理解するのに役立つだけです.

次のコードを作成しました。

extension Array {
    func max<T, U : Comparable>(f: T -> U ) -> U? {
        var maxSoFar : U? = nil
        for i in self {
            var itemValue = f(i as T)
            if(maxSoFar == nil) {
                maxSoFar = itemValue
            }
            if itemValue > maxSoFar {
                maxSoFar = itemValue
            }
        }
        return maxSoFar
    }

    func min<T, U : Comparable>(f: T -> U ) -> U? {
        var minSoFar : U? = nil
        for i in self {
            var itemValue = f(i as T)
            if(minSoFar == nil) {
                minSoFar = itemValue
            }
            if itemValue < minSoFar {
                minSoFar = itemValue
            }
        }
        return minSoFar
    }
}

テストするために、基本的な Person クラスを作成しました。

class Person {
    var name : String
    var age : Float

    init(name: String, age: Float) {
        self.name = name
        self.age = age
    }
}

私がクロージャーで明示的である場合、これらのケースではうまくいくようです:

var maximumAge = [Person(name: "Bob", age: 42), Person(name:"Mary", age:40)]
    .max{ (p: Person) in p.age }! // Gives 42

var min = [100, 101].min{ (i: Int) in i }! // Gives 100

ただし、極端な省略形を使用するための型を推測することはできません。

var maximumAge = [Person(name: "Bob", age: 42), Person(name:"Mary", age:40)]
    .max{ $0.age }! // Error

var min = [100, 101].min{ $0 }! // Error

または中程度の長さ:

var maximumAge = [Person(name: "Bob", age: 42), Person(name:"Mary", age:40)]
    .max{p in p.age }! // Error

var min = [100, 101].min{ i in i }! // Error

誰かがこれについてまだ専門家である場合、私が間違っていることを教えてもらえますか? ここまでたどり着くのにかなりの読書とハッキングが必要だったことを認めなければなりません!

返信ありがとうございます

4

1 に答える 1

3

max(and ) を次のように定義するとmin:

func max<T, U : Comparable>(f: T -> U ) -> U?

あなたは実際に、クロージャーfがの要素とは異なるタイプを取るかもしれないと言っていますArrayArrayは既に汎用の structであるため、既に定義されているArray<T>要素の型を再利用できます。Swift 言語ガイドTから:

ジェネリック型を拡張する場合、拡張の定義の一部として型パラメーター リストを提供しません。代わりに、元の型定義の型パラメーター リストは拡張機能の本体内で使用でき、元の型パラメーター名は元の定義の型パラメーターを参照するために使用されます。

したがって、要素の型Tは既に利用可能であるため、次のTように型パラメーター リストから単に取り出します。

func max<U : Comparable>(f: T -> U ) -> U?

これにより、クロージャーがの要素fと同じ型を取ることが保証されます。その後、コンパイラは、テスト ケースで使用している型を正しく推測し、表示されているエラーを修正できます。TArray

于 2014-09-30T18:25:39.777 に答える