Bạn có thể thử một số chương trình meta để đạt được mục tiêu của bạn.
Xem đoạn mã sau:
class OverloadError < ArgumentError; end
class Class
=begin rdoc
=end
def define_overload_method(methodname, *methods)
methods.each{ | proc |
define_method("#{methodname}_#{proc.arity}".to_sym, &proc)
}
define_method(methodname){|*x|
if respond_to?("#{methodname}_#{x.size}")
send "#{methodname}_#{x.size}", *x
else
raise OverloadError, "#{methodname} not defined for #{x.size} parameters"
end
}
end
end
class X
define_overload_method :ometh,
Proc.new{ "Called me with no parameter" },
Proc.new{ |p1| "Called me with one parameter (#{p1.inspect})" },
Proc.new{ |p1,p2| "Called me with two parameter (#{p1.inspect}, #{p2.inspect})" }
end
x = X.new
p '----------'
p x.ometh()
p x.ometh(1)
p x.ometh(1,2)
p x.ometh(1,2,3) #OverloadError
Bạn có thể xác định phương pháp quá tải của bạn với define_overload_method
. Tham số là tên phương thức và danh sách các thủ tục. Phương thức methodname
được tạo và gọi phương thức tương ứng. Phương pháp nào được xác định bởi số tham số (Không gõ!).
Một cú pháp thay thế sẽ là:
class OverloadError < ArgumentError; end
class Class
def def_overload(methodname)
define_method(methodname){|*x|
if respond_to?("#{methodname}_#{x.size}")
send "#{methodname}_#{x.size}", *x
else
raise OverloadError, "#{methodname} not defined for #{x.size} parameters"
end
}
end
def overload_method(methodname, proc)
define_method("#{methodname}_#{proc.arity}".to_sym, &proc)
end
end
class X
def_overload :ometh
overload_method :ometh, Proc.new{ "Called me with no parameter" }
overload_method :ometh, Proc.new{ |p1| "Called me with one parameter (#{p1.inspect})" }
overload_method :ometh, Proc.new{ |p1,p2| "Called me with two parameter (#{p1.inspect}, #{p2.inspect})" }
end
def_overload
xác định khung cho các phương pháp quá tải của bạn, overload_method
định nghĩa một 'quá tải-phương pháp'.
Nhưng như đã mentioned by Holger:
Bạn nên cố gắng để thích ứng với cách Ruby. Có một lý do tại sao không có quá tải trong Ruby. Phương pháp chỉ nên làm một điều, không phải là một cách kỳ diệu quyết định làm những điều khác biệt rất lớn chỉ vì những lập luận khác nhau. Thay vào đó, hãy thử tận dụng lợi thế của Duck Typing và nếu nghi ngờ, hãy sử dụng các phương thức khác nhau với các tên có ý nghĩa.
Tôi đã tò mò làm thế nào tôi có thể thực hiện một phiên bản với loại quá tải nhạy cảm.Ở đây là:
class OverloadError < ArgumentError; end
class Class
def def_overload(methodname)
define_method(methodname){|*x|
methname = "xxx"
methname = "#{methodname}_#{x.size}#{x.map{|p| p.class.to_s}.join('_')}"
if respond_to?(methname)
send methname, *x
elsif respond_to?("#{methodname}_#{x.size}")
send "#{methodname}_#{x.size}", *x
else
raise OverloadError, "#{methodname} not defined for #{x.size} parameters"
end
}
end
def overload_method(methodname, *args, &proc)
types = []
args.each{|arg| types << arg.to_s}
define_method("#{methodname}_#{proc.arity}#{types.join('_')}".to_sym, &proc)
end
end
class X
def_overload :ometh
overload_method(:ometh){ "Called me with no parameter" }
overload_method(:ometh, String){ |p1| "Called me with one string parameter (#{p1.inspect})" }
overload_method(:ometh){ |p1| "Called me with one parameter (#{p1.inspect})" }
overload_method(:ometh){ |p1,p2| "Called me with two parameter (#{p1.inspect}, #{p2.inspect})" }
end
Khi bạn gọi nó với
p x.ometh(1)
p x.ometh('a')
Bạn nhận được
"Called me with one parameter (1)"
"Called me with one string parameter (\"a\")"
Tôi không thích tùy chọn độ dài ... vì arg có thể được chuyển thành nil .. ít nhất thì điều này rất khó đọc. – Arth
Bạn nên cố gắng thích ứng với cách Ruby. Có một lý do tại sao không có quá tải trong Ruby. Phương pháp chỉ nên làm một điều, không phải là một cách kỳ diệu quyết định làm những điều khác biệt rất lớn chỉ vì những lập luận khác nhau. Thay vào đó, hãy tận dụng lợi thế của [Nhập tên con vịt] (http://en.wikipedia.org/wiki/Duck_typing) và nếu nghi ngờ, hãy sử dụng các phương pháp khác nhau với các tên có ý nghĩa. –
Một yêu cầu khác: Chỉ tải quá nhiều với số tham số (như trong ví dụ của bạn) hoặc cũng với loại tham số? Hoặc trong một ví dụ: Phương thức có gọi 'a (1)' và 'a ('x')' cùng một cuộc gọi hoặc thực hiện cuộc gọi các phương thức khác nhau không? – knut