2014-09-30 257 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