2016-11-21 4 views
0

Angenommen, ich habe eine Funktion als solche überlastet:über Swift-Funktionen, benannte Parameter und Typen Management

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

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

Randbemerkung: Funktion average selbst überlastet ist sowohl ein Array als Eingang oder eine Liste von Parametern zu akzeptieren .

Zwei Fragen:

1 - Wie verweisen ich die Funktion, die ich mich beziehe?

Zum Beispiel:

let doAverage = doMath(mathOption: "average") 

Wie gebe ich die doMath Funktion Ich rufe? Swift ist verwirrt und kann von der nächsten Zeile nicht folgern:

Wenn ich später schreiben:

doAverage(1,2,3,4) 

2 - Wie nenne ich Parameter? Die ursprüngliche Durchschnittsfunktion heißt also:

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

Ich muss die Parameter nennen. Mit doAverage kann ich jedoch keine Parameter angeben, da der Rückgabetyp definiert ist.

3 - Wie könnte ich einen Typ erstellen (vielleicht mit struct?), Um diesen hypothetischen Code zu vereinfachen.

Vielen Dank für Ihre Hilfe, Erklärung oder Antworten, die Sie anbieten!


bearbeiten, bis 3 zu verdeutlichen, hier ist die erweiterte Version der Situation:

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 
} 

I typealias verwendet haben zwei Beispiel-Typen zu erstellen. Könnte ein Typ irgendwie überladen werden, um beide Situationen zu bewältigen? Für mich macht dies Sinn, wenn die gleiche Funktion überladen wird, um verschiedene Eingaben zu handhaben, warum nicht der Typ? Vielleicht ist dies eine naive Perspektive oder vielleicht gibt es eine Möglichkeit, auszudrücken, was ich in Swift denke?

+0

Ihre dritte Frage sehr unklar ist. Sie können den Code nicht vereinfachen, der nur hypothetisch ist, ohne Anwendungsfälle etc. zu zeigen. – Sulthan

+0

Hey @Sultan, danke für dein Feedback, ich habe meine Frage hinzugefügt, um es zu klären. Lass es mich wissen, wenn es jetzt mehr Sinn macht. – Babak

Antwort

0

Wie wird die Funktion referenziert? Gib einfach den Typ an!

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)) 

oder

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

würde ich auch raten, diese Art zu nennen typealias verwenden.

Ihre zweite Frage - Sie können Parameter in Funktionstypen nicht benennen.

+0

Danke! Wenn also Parameter in Funktionstypen nicht benannt werden können, ist es möglich, einen Strukturtyp oder einen Klassentyp zurückzugeben, wobei die Rückkehrinstanz benannte Parameter annehmen kann? – Babak

+0

@Babak Oder Sie können einen Typ zurückgeben, der ein Protokoll implementiert. – Sulthan

+0

Wie würden Sie dies mit einem Typ lösen, der hier ein Protokoll implementiert? – Babak

0

Sie können die gewünschte Funktion an doMath als Parameter übergeben. Und verwenden Sie Generika, so dass Sie einige Erweiterbarkeit haben.

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

    return op(value) 

} 

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

Edit: Es hat Probleme mit dem variadic Parameter. Eine andere Bearbeitung: Es wurde eine Problemumgehung gefunden.

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 

Auch hier ist ein schöner Weg, das schreiben reduzieren:

Double(nums.reduce(0, +)) 
Verwandte Themen