Câu trả lời:
Quá tải phương thức có thể đạt được bằng cách khai báo hai phương thức có cùng tên và chữ ký khác nhau. Những chữ ký khác nhau có thể là một trong hai
method(int a, int b) vs method(String a, String b)
method(a) vs method(a, b)
Chúng ta không thể đạt được quá tải phương thức bằng cách đầu tiên vì không có khai báo kiểu dữ liệu trong ruby ( ngôn ngữ gõ động ). Vì vậy, cách duy nhất để xác định phương pháp trên làdef(a,b)
Với tùy chọn thứ hai, có vẻ như chúng ta có thể đạt được quá tải phương thức, nhưng chúng ta không thể. Giả sử tôi có hai phương thức với số lượng đối số khác nhau,
def method(a); end;
def method(a, b = true); end; # second argument has a default value
method(10)
# Now the method call can match the first one as well as the second one,
# so here is the problem.
Vì vậy, ruby cần duy trì một phương thức trong phương thức tra cứu chuỗi với một tên duy nhất.
"Quá tải" là một thuật ngữ đơn giản thậm chí không có ý nghĩa trong Ruby. Nó cơ bản là một từ đồng nghĩa với "văn lập luận dựa trên tĩnh", nhưng Ruby không có công văn tĩnh gì cả . Vì vậy, lý do tại sao Ruby không hỗ trợ công văn tĩnh dựa trên các đối số, là vì nó không hỗ trợ công văn tĩnh, thời gian. Nó không hỗ trợ công văn tĩnh dưới bất kỳ hình thức nào , cho dù dựa trên đối số hay cách khác.
Bây giờ, nếu bạn không thực sự hỏi cụ thể về việc quá tải, nhưng có thể về công văn dựa trên đối số động , thì câu trả lời là: vì Matz đã không thực hiện nó. Bởi vì không ai bận tâm đề xuất nó. Bởi vì không ai bận tâm để thực hiện nó.
Nói chung, công văn dựa trên đối số động trong một ngôn ngữ với các đối số tùy chọn và danh sách đối số có độ dài thay đổi, rất khó để có được quyền, và thậm chí còn khó hơn để giữ cho nó dễ hiểu. Ngay cả trong các ngôn ngữ có công văn dựa trên đối số tĩnh và không có đối số tùy chọn (ví dụ như Java), đôi khi hầu như không thể nói cho một phàm nhân, mà quá tải sẽ được chọn.
Trong C #, bạn thực sự có thể mã hóa bất kỳ vấn đề 3-SAT nào thành độ phân giải quá tải, điều đó có nghĩa là độ phân giải quá tải trong C # là NP-hard.
Bây giờ hãy thử điều đó với công văn động , nơi bạn có thứ nguyên thời gian bổ sung để giữ trong đầu.
Có những ngôn ngữ tự động gửi dựa trên tất cả các đối số của một thủ tục, trái ngược với các ngôn ngữ hướng đối tượng, chỉ gửi các self
đối số zeroth "ẩn" . Ví dụ, Lisp chung gửi các kiểu động và thậm chí các giá trị động của tất cả các đối số. Clojure gửi đến một hàm tùy ý của tất cả các đối số (mà BTW cực kỳ hay và cực kỳ mạnh mẽ).
Nhưng tôi không biết bất kỳ ngôn ngữ OO nào với công văn dựa trên đối số động. Martin Oderky nói rằng anh ta có thể xem xét việc thêm công văn dựa trên đối số vào Scala, nhưng chỉ khi anh ta có thể loại bỏ quá tải cùng một lúc và tương thích ngược với cả mã Scala hiện có sử dụng quá tải và tương thích với Java (anh ta đặc biệt đề cập đến Swing và AWT chơi một số thủ thuật cực kỳ phức tạp thực hiện khá nhiều trường hợp góc tối khó chịu của các quy tắc quá tải khá phức tạp của Java). Bản thân tôi đã có một số ý tưởng về việc thêm công văn dựa trên đối số vào Ruby, nhưng tôi không bao giờ có thể tìm ra cách thực hiện theo cách tương thích ngược.
def method(a, b = true)
sẽ không hoạt động, do đó quá tải phương thức là không thể." Nó không thể; thật khó khăn Tôi tìm thấy câu trả lời NÀY thực sự nhiều thông tin, tuy nhiên.
Tôi đoán bạn đang tìm kiếm khả năng để làm điều này:
def my_method(arg1)
..
end
def my_method(arg1, arg2)
..
end
Ruby hỗ trợ điều này theo một cách khác:
def my_method(*args)
if args.length == 1
#method 1
else
#method 2
end
end
Một mô hình phổ biến cũng là để vượt qua trong các tùy chọn dưới dạng băm:
def my_method(options)
if options[:arg1] and options[:arg2]
#method 2
elsif options[:arg1]
#method 1
end
end
my_method arg1: 'hello', arg2: 'world'
Mong rằng sẽ giúp
Quá tải phương thức có ý nghĩa trong một ngôn ngữ với kiểu gõ tĩnh, nơi bạn có thể phân biệt giữa các loại đối số khác nhau
f(1)
f('foo')
f(true)
cũng như giữa số lượng đối số khác nhau
f(1)
f(1, 'foo')
f(1, 'foo', true)
Sự phân biệt đầu tiên không tồn tại trong ruby. Ruby sử dụng kiểu gõ động hoặc "gõ vịt". Sự khác biệt thứ hai có thể được xử lý bằng các đối số mặc định hoặc bằng cách làm việc với các đối số:
def f(n, s = 'foo', flux_compensator = true)
...
end
def f(*args)
case args.size
when
...
when 2
...
when 3
...
end
end
Điều này không trả lời câu hỏi tại sao ruby không bị quá tải phương thức, nhưng các thư viện bên thứ ba có thể cung cấp nó.
Các contracts.ruby thư viện cho phép quá tải. Ví dụ được điều chỉnh từ hướng dẫn:
class Factorial
include Contracts
Contract 1 => 1
def fact(x)
x
end
Contract Num => Num
def fact(x)
x * fact(x - 1)
end
end
# try it out
Factorial.new.fact(5) # => 120
Lưu ý rằng điều này thực sự mạnh hơn so với quá tải của Java, bởi vì bạn có thể chỉ định các giá trị khớp với (ví dụ 1
), không chỉ các loại.
Bạn sẽ thấy hiệu suất giảm khi sử dụng điều này mặc dù; bạn sẽ phải chạy điểm chuẩn để quyết định mức độ bạn có thể chịu đựng được.
Tôi thường làm cấu trúc sau:
def method(param)
case param
when String
method_for_String(param)
when Type1
method_for_Type1(param)
...
else
#default implementation
end
end
Điều này cho phép người dùng của đối tượng sử dụng phương thức rõ ràng và phương thức rõ ràng: Nếu anh ta muốn tối ưu hóa thực thi, anh ta có thể gọi trực tiếp phương thức chính xác.
Ngoài ra, nó làm cho bài kiểm tra của bạn rõ ràng hơn và betters.
đã có câu trả lời tuyệt vời về lý do tại sao bên của câu hỏi. tuy nhiên, nếu bất cứ ai tìm kiếm các giải pháp khác hãy kiểm tra đá quý ruby chức năng được lấy cảm hứng từ các tính năng khớp mẫu của Elixir .
class Foo
include Functional::PatternMatching
## Constructor Over loading
defn(:initialize) { @name = 'baz' }
defn(:initialize, _) {|name| @name = name.to_s }
## Method Overloading
defn(:greet, :male) {
puts "Hello, sir!"
}
defn(:greet, :female) {
puts "Hello, ma'am!"
}
end
foo = Foo.new or Foo.new('Bar')
foo.greet(:male) => "Hello, sir!"
foo.greet(:female) => "Hello, ma'am!"