【问题标题】:Swift Generics Type Inference ExtensionsSwift 泛型类型推断扩展
【发布时间】:2014-09-30 17:25:31
【问题描述】:

我正在尝试通过为 Array 类创建 Min 和 Max 扩展(类似于 C# 中的 Min 和 Max Extension 方法)来建立我对 Swift 中的泛型的理解。可能有更好的方法来做到这一点,但正如我所说,它只是为了帮助我理解泛型。

我创建了以下代码:

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

如果有人是这方面的专家,你能告诉我我做错了什么吗?我不得不承认,我花了相当多的阅读和破解才能走到这一步!

提前感谢您的任何回复

【问题讨论】:

标签: swift generics swift-extensions


【解决方案1】:

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

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

您实际上是在说闭包f 可能采用与Array 中的元素不同的类型。由于Array 已经是一个通用结构Array&lt;T&gt;,您可以重新使用它已经定义的元素类型T。来自the Swift language guide

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

所以,既然元素类型T 已经可供您使用,只需将T 从类型参数列表中取出,如下所示:

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

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

【讨论】:

  • 太棒了!感谢您的帮助
  • 这还可以让您在调用 f() 时摆脱 as T,因为 T 现在是数组的基础基本类型。
  • 现在我还可以移除 var itemValue = f(i as T) 上的强制转换并简化为 let itemValue = f(i)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-15
  • 2019-05-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多