2014-09-30 212 views
3

我想通过为Array类创建Min和Max扩展(类似于C#中的Min和Max扩展方法)来建立我对Swift中泛型的理解。可能有更好的方法来做到这一点,但正如我所说,这只是为了帮助我理解泛型。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 

如果有人有这方面的专家呢,你可以让我知道我做错了吗?我不得不承认,我花了一些时间阅读和骇客来获得这些!

预先感谢任何答复

+0

您可能对我的[相关问题](http://stackoverflow.com/q/26228506/27779)和[gist](https://gist.github.com/Revolucent/1a8085746b950d91a0a8)感兴趣,以解决同样的问题。 – 2014-10-09 14:44:50

回答

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将采取相同的键入TArray中的元素。然后,编译器可以正确地推断出您在测试用例中使用的是哪些类型,并修复了您所看到的错误。

+0

太棒了!感谢您的帮助 – fabiossa 2014-09-30 19:04:21

+1

由于'T'现在是数组的底层基类型,因此这还可以让您在调用'f()'时将'as'移除。 – 2014-09-30 19:05:04

+0

现在我也可以删除var itemValue = f(我作为T)上的强制转换并简化为让itemValue = f(i) – fabiossa 2014-09-30 19:07:02