2016-11-21 50 views
0

假設我有一個函數重載這樣:關於SWIFT功能,命名參數和類型管理

func doMath(mathOption: String) -> (Int...) -> Double { 
    ... 
    return average 
} 

func doMath(mathOption: String) -> ([Int]) -> Double { 
    ... 
    return average 
} 

邊注:功能average本身超載同時接受數組作爲輸入或參數列表。

兩個問題:

1 - 我如何引用我指的是哪一個函數?

例如:

let doAverage = doMath(mathOption: "average") 

如何指定我打電話其中doMath功能?斯威夫特是一頭霧水,不能從下一行推斷:

如果我後來寫:

doAverage(1,2,3,4) 

2 - 我該如何命名的參數?原來的平均功能被稱爲:

average(nums: 1,2,3,4) 

我必須命名參數。然而,對於doAverage,我無法命名參數,因爲返回類型是如何定義的。

3 - 如何創建一個類型(可能使用struct?)來簡化這個假設代碼。

感謝您提供任何幫助,解釋或答案!


編輯,澄清3,這裏的情況擴展版本:

func sumAll(nums: [Int]) -> Double { 
    return Double(nums.reduce(0, { (a,b) in a+b})) 
} 

func sumAll(nums: Int...) -> Double { 
    return sumAll(nums: nums) 
} 


func average(nums: [Int]) -> Double { 
    return sumAll(nums: nums)/Double(nums.count) 
} 

func average(nums: Int...) -> Double { 
    return average(nums: nums) 
} 

func doMath(mathOption: String, nums: Int...) -> Double { 
    if mathOption == "average" { 
     return average(nums: nums) 
    } else { 
     return sumAll(nums: nums) 
    } 
} 

typealias mathReturnType1 = (Int...) -> Double 
typealias mathReturnType2 = ([Int]) -> Double 


func doMath(mathOption: String) -> mathReturnType1 { 
    return average 
} 

func doMath(mathOption: String) -> mathReturnType2 { 
    return average 
} 

我用typealias創建兩個實例的類型。某種類型是否可以以某種方式處理這兩種情況?對我來說,這是有道理的,如果相同的函數被重載來處理不同的輸入,爲什麼不是類型?也許這是一個天真的觀點,或者有一種方法可以表達我在Swift中的想法?

+0

你的第三個問題是非常不清楚。你不能簡化只是假設的代碼,不會顯示用例等。 – Sulthan

+0

嗨@Sulthan,感謝您的反饋,我已經添加了我的問題來澄清它。讓我知道現在是否更有意義。 – Babak

回答

0

如何引用該函數?只需指定類型!

func doMath(mathOption: String) -> (Int...) -> Double { 
    return { (values: Int...) -> Double in 
     return Double(values.reduce(0, +))/Double(values.count) 
    } 
} 

func doMath(mathOption: String) -> ([Int]) -> Double { 
    return { (values: [Int]) -> Double in 
     return Double(values.reduce(0, +))/Double(values.count) 
    } 
} 

let average1 = doMath(mathOption: "x") as (Int...) -> Double 
print(average1(1, 2, 3)) 

let average1: (Int...) -> Double = doMath(mathOption: "x") 
print(average1(1, 2, 3)) 

我也建議對名稱中使用一個typealias該類型。

你的第二個問題 - 你不能在函數類型中命名參數。

+0

謝謝!因此,如果我們無法在函數類型中使用命名參數,是否可以傳回結構類型或類類型,從而返回實例可以接受命名參數? – Babak

+0

@Bakak或者你可以返回一個實現協議的類型。 – Sulthan

+0

你會如何解決這個使用實現協議的類型在這裏? – Babak

0

您可以將您想要完成的功能作爲參數傳遞給doMath。並使用泛型,所以你有一些可擴展性。

func doMath<T>(using op: (T) -> Double, with value: T) -> Double { 

    return op(value) 

} 

doMath(using: sumAll, with: [1,2,3]) 
// returns 6 

編輯:它的可變參數有問題。 另一編輯:找到一種解決方法。

func doMath<T>(using op: ([T]) -> Double, with value: T...) -> Double { 

    return op(value) 

} 

func doMath<T>(using op: (T) -> Double, with value: T) -> Double { 

    return op(value) 

} 

doMath(using: sumAll, with: 1,2,3,4,5) //15 
doMath(using: sumAll, with: [1,2,3,4,5]) // 15 

而且,這裏是編寫減少漂亮的方式:

Double(nums.reduce(0, +))