2015-04-07 6 views
6

Sto creando un metodo per una classe in swift con 2 argomenti e sono entrambi facoltativi. tuttavia, ho bisogno di almeno uno di loro ad essere popolata per il metodo di lavorare con successo, non importa qualeArgomenti del metodo opzionale Swift ma almeno uno deve essere compilato

func someMethod(arg1: Sometype?, arg2: Sometype?)-> Void { 
     //I need at least one argument to 
     //be populated to do what i need 
} 

In Objective-C che potrebbe gettare un'asserzione se entrambi questi oggetti era pari a zero. a Swift I "m chiedo se c'è un modo migliore per farlo che un'asserzione

risposta

4

Sono d'accordo con Airspeed Velocity che dovresti usare i sovraccarichi qui, ma li farei in modo diverso. Sbarazzati completamente degli optionals.

func someMethod(#arg1: Sometype)-> Void {} 

func someMethod(#arg2: Sometype)-> Void {} 

func someMethod(#arg1: Sometype, #arg2: Sometype) -> Void {} 

A questo punto, dovrebbe essere ovvio che questi sono davvero diversi metodi:

func someMethodWithArg1(arg1: Sometype)-> Void {} 

func someMethodWithArg2(arg2: Sometype)-> Void {} 

func someMethod(#arg1: Sometype, #arg2: Sometype) -> Void {} 

per rendere questo concreto, considerare se stavamo facendo una classe FixedLengthString che si potrebbe passare una lunghezza, o una stringa esistente, oppure puoi passare entrambi e ripeterebbe la stringa fino a riempire la lunghezza.

quello che stai descrivendo sarebbe:

func makeString(length: Int?, string: String?) -> FixedString 

Ma piuttosto che quello, basta fare i metodi:

func makeStringWithLength(length: Int) -> FixedString 
func makeStringFromString(string: String) -> FixedString 
func makeStringByFillingWith(string: String, totalLength: Int) -> FixedString 

Questo rende più chiaro come funziona il tutto, e non è possibile chiamare non correttamente. È così che dovresti farlo anche in ObjC.

+0

Penso che questo abbia più senso e rende chiaro l'intento, grazie – bolnad

2

Si potrebbe utilizzare sovraccarico invece:.

// arg1 cannot be nil 
func someMethod(arg1: Int, arg2: Int?)-> Void { 
    println("arg2 was nil") 
    somePrivateMethod(arg1,arg2) 
} 

// arg2 cannot be nil 
func someMethod(arg1: Int?, arg2: Int)-> Void { 
    println("arg1 was nil") 
    somePrivateMethod(arg1,arg2) 
} 

// this version is needed to avoid annoying "ambiguous call" 
// errors when passing two non-optionals in... 
func someMethod(arg1: Int, arg2: Int)-> Void { 
    println("neither was nil") 
    somePrivateMethod(arg1,arg2) 
} 

private func somePrivateMethod(arg1: Int?, arg2: Int?)-> Void { 
    // private method in which at least arg1 or arg2 will be guaranteed non-nil 
} 


someMethod(1, nil) // prints "arg2 was nil" 
someMethod(nil, 1) // prints "arg1 was nil" 
someMethod(1, 1) // prints "neither was nil" 

// but if you try this: 
someMethod(nil, nil) // error: cannot find an overload for 'someMethod' 
         // that accepts an argument list of type '(nil, nil)' 

Il rovescio della medaglia è che il chiamante è costretto a scartare gli argomenti - semplicemente non possono passare due optional senza che uno di essi sia non-zero, ma questa è una caratteristica, non un bug! In quanto significa che è fisicamente impossibile per il chiamante chiamare accidentalmente l'API "il torto modo "e generare una asserzione

Naturalmente, questo porta alla domanda se davvero vuoi sovraccarichi multipli che richiedono numeri diversi argomenti o tipi diversi (vedi la risposta di Rob), che vale anche la pena considerare nel contesto del tuo caso d'uso.

+0

sui metodi in cui un arg deve essere lì, dovrebbe avere un! someMethod (arg1: Int !, arg2: Int?), someMethod (arg1: In ?, arg2: Int!) – bolnad

+1

Molto decisamente no. Un 'Int! 'È solo un' Int? 'Che è" implicitamente "non appreso quando lo si usa. Se hai scritto 'func someMethod (arg1: Int !, arg2: Int?) -> Void', puoi chiamarlo' someMethod (nil, nil) ', sconfiggendo l'applicazione basata sul tipo che almeno uno non è nulla. –

+0

ooh ok grazie per i chiarimenti, darò uno scatto – bolnad

Problemi correlati