Usted podría intentar un poco de programación meta para llegar a su objetivo.
Véase el siguiente código:
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
puede definir su método sobrecargado con define_overload_method
. Los parámetros son el nombre del método y una lista de procedimientos. Se crea el método methodname
y llama al método correspondiente. Qué método está determinado por la cantidad de parámetros (¡No escriba!).
una sintaxis alternativa sería:
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
define el marco para sus métodos sobrecargados, overload_method
define una 'sobrecarga-método'.
Pero como ya se ha mentioned by Holger:
Usted debe tratar de adaptarse a la forma de Ruby. Hay una razón por la cual no hay sobrecarga en Ruby. Los métodos solo deberían hacer una cosa, no mágicamente decidir hacer cosas muy diferentes solo por diferentes argumentos. En su lugar, intente aprovechar Duck Typing y, en caso de duda, utilice diferentes métodos con nombres significativos.
tenía curiosidad cómo podría implementar una versión con el tipo de sobrecarga sensible.Aquí está:
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
Cuando se llama con
p x.ometh(1)
p x.ometh('a')
Se obtiene
"Called me with one parameter (1)"
"Called me with one string parameter (\"a\")"
No me gusta la opción de longitud ... ya que los argumentos se pueden pasar como nulos ... al menos esto es difícil de leer. – Arth
Deberías intentar adaptarte a la manera Ruby. Hay una razón por la cual no hay sobrecarga en Ruby. Los métodos solo deberían hacer una cosa, no mágicamente decidir hacer cosas muy diferentes solo por diferentes argumentos. En su lugar, intente aprovechar [Duck Typing] (http://en.wikipedia.org/wiki/Duck_typing) y, en caso de duda, utilice diferentes métodos con nombres significativos. –
Una consulta adicional: ¿Sobrecarga solo con el número de parámetros (como en su ejemplo) o también con el tipo de parámetro? O en un ejemplo: ¿El método llama 'a (1)' y 'a ('x')' a la misma llamada o hace la llamada a diferentes métodos? – knut