2012-01-02 4 views
8

Tôi có một phương thức với đối số tùy chọn. Làm cách nào tôi có thể quyết định liệu Đối số có được đưa ra hay không?Cách quyết định xem đối số tùy chọn đã được đưa ra hay không theo phương pháp ruby ​​

Tôi đã đưa ra các giải pháp sau. Tôi hỏi câu hỏi này vì tôi không hoàn toàn hài lòng với bất kỳ câu hỏi nào trong số họ. Hiện có một tốt hơn?

nil như giá trị mặc định

def m(a= nil) 
    if a.nil? 
     ... 
    end 
end 

Hạn chế với một này là, rằng nó không thể được quyết định dù không có đối số hoặc nil đã được đưa ra.

tùy chỉnh NoArgument như giá trị mặc định

class NoArgument 
end 

def m(a= NoArgument.new) 
    if NoArgument === a 
     ... 
    end 
end 

nil đã được đưa ra có thể được quyết định, nhưng cùng một vấn đề tồn tại cho trường hợp của NoArgument.

Đánh giá kích thước của một ellipsis

def m(*a) 
    raise ArgumentError if m.size > 1 
    if m.size == 1 
     ... 
    end 
end 

Trong phiên bản này nó có thể luôn luôn quyết định liệu các đối số tùy chọn đã được đưa ra. Tuy nhiên, Proc#arity của phương pháp này đã thay đổi từ 1 đến -1 (không đúng, xem nhận xét). Nó vẫn có những bất lợi của việc nuôi ong tồi tệ hơn đối với tài liệu và cần phải tự nâng cao ArgumentError.

+1

Lệnh 'arity' của tất cả các phương pháp của bạn là' -1'. Hạn chế duy nhất của giải pháp cuối cùng là bạn phải tự kiểm tra rằng không có nhiều hơn một đối số được đưa ra và tài liệu là cần thiết để biết các đối số là gì. –

Trả lời

15

Jorg W Mittag có following code snippet có thể làm những gì bạn muốn:

def foo(bar = (bar_set = true; :baz)) 
    if bar_set 
    # optional argument was supplied 
    end 
end 
+0

Điều gì sẽ là một trường hợp sử dụng cho điều này? – AndrewF

+1

@AndrewF: Câu hỏi đó sẽ được trả lời tốt hơn bởi johannes hoặc Jorg W Mittag. –

+0

Có một số phương pháp trong thư viện lõi hoạt động khác nhau tùy thuộc vào số lượng đối số được cung cấp. Trong thực tế, họ mô phỏng công văn dựa trên đối số. Trong hầu hết các triển khai của Ruby, các phương thức này được thực hiện trong C, C++, Java, C# v.v. và chúng có quyền truy cập đặc quyền vào nội bộ của Ruby, vì vậy chúng có thể thực sự đơn giản kiểm tra số đối số. Nhưng, nếu bạn muốn viết một phương thức tương thích trong Ruby, bạn phải sử dụng các thủ thuật như thế này. –

4

Làm thế nào về

NO_ARGUMENT = Object.new 

def m(a = NO_ARGUMENT) 
    if a.equal?(NO_ARGUMENT) 
     #no argument given 
    end 
end 
+0

Đây là phương pháp được Rubinius sử dụng, chẳng hạn. –

+1

Điểm bất lợi duy nhất với phương pháp này là phương pháp này có thể quyết định truyền 'NO_ARGUMENT' làm đối số cho phương thức khác sử dụng thành ngữ này. –