2015-04-07 16 views
6

Tôi đang tạo phương thức cho một lớp nhanh bằng 2 đối số và cả hai đều là tùy chọn. Tuy nhiên, tôi cần ít nhất một trong số họ để được áp dụng cho phương pháp để làm việc thành công, nó không quan trọng mà mộtĐối số phương thức tùy chọn Swift nhưng ít nhất một đối số cần được điền

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

Trong Objective-c chúng ta có thể ném một Khẳng định nếu cả hai đối tượng là con số không. trong Swift i "m tự hỏi nếu có một cách tốt hơn để làm điều này hơn một assert

Trả lời

4

Tôi đồng ý với Tốc độ bay mà bạn nên sử dụng quá tải ở đây, nhưng tôi sẽ làm cho chúng khác nhau. Loại bỏ các tùy chọn hoàn toàn.

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

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

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

Tại thời điểm đó, nó nên được rõ ràng rằng đây là những phương pháp thực sự khác nhau:

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

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

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

Để làm cho bê tông này, hãy xem xét nếu chúng tôi đã thực hiện một lớp FixedLengthString mà bạn có thể vượt qua một chiều dài tới, hoặc một chuỗi hiện có, hoặc bạn có thể vượt qua cả hai và nó sẽ lặp lại chuỗi cho đến khi nó đầy chiều dài.

Những gì bạn đang mô tả sẽ là:

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

Nhưng thay vì vậy, chỉ cần thực hiện các phương pháp:

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

này làm cho nó rõ ràng hơn như thế nào mọi thứ hoạt động, và bạn không thể gọi nó không đúng. Đây là cách bạn nên làm nó trong ObjC, quá.

+0

Tôi nghĩ điều này có ý nghĩa nhất và làm cho ý định rõ ràng, cảm ơn – bolnad

2

Bạn có thể sử dụng quá tải thay vì:.

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

Nhược điểm của việc này là người gọi buộc phải unwrap các đối số - họ không thể vượt qua hai tùy chọn trong mà không kiểm tra tại vì sợ rằng một trong số họ là không nil Nhưng đây là một tính năng, không phải là một lỗi! cách "và tạo ra một khẳng định.

Tất nhiên, điều này dẫn đến câu hỏi liệu bạn có thực sự muốn nhiều lần quá tải khác nhau không bers các đối số hoặc các loại khác nhau (xem câu trả lời của Rob), cũng đáng xem xét trong bối cảnh trường hợp sử dụng của bạn.

+0

về các phương pháp mà một arg cần phải ở đó, nếu nó có! someMethod (arg1: Int !, arg2: Int?), someMethod (arg1: In ?, arg2: Int!) – bolnad

+1

Rất chắc chắn là không. Một 'Int!' Chỉ là một 'Int?' Mà là "ngầm" không được mở ra khi bạn sử dụng nó. Nếu bạn đã viết 'func someMethod (arg1: Int !, arg2: Int?) -> Void' thì bạn có thể gọi nó là' someMethod (nil, nil) ', đánh bại thực thi dựa trên kiểu mà ít nhất một là non-nil. –

+0

ooh okay cảm ơn vì đã giải thích rõ, tôi sẽ cung cấp cho ảnh này – bolnad

Các vấn đề liên quan