Swift泛型类型推理扩展

时间:2014-09-30 17:25:31

标签: swift generics swift-extensions

我试图通过为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

如果有人是这方面的专家,你能告诉我我做错了什么吗?我不得不承认,为了达到这个目的,我花了很多时间阅读和黑客攻击!

提前感谢您的回复

1 个答案:

答案 0 :(得分:3)

当您像这样定义max(和min)时:

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

你实际上是说封闭f可能采用与Array中的元素不同的类型。由于Array已经是通用结构Array<T>,因此您可以重复使用已定义的元素类型T。来自the Swift language guide

  

扩展泛型类型时,不提供类型参数   列表作为扩展定义的一部分。相反,类型   原始类型定义中的参数列表可在其中使用   扩展的主体,以及原始类型参数名称   用于引用原始定义中的类型参数。

因此,由于您已经可以使用元素类型T,只需从类型参数列表中取出T,如下所示:

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

这可以保证闭包f采用与T中的元素相同的Array类型。然后,编译器可以正确地推断出您在测试用例中使用的类型,并修复了您看到的错误。