Si potrebbe provare un po 'di programmazione meta per raggiungere il tuo obiettivo.
vedere il codice seguente:
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
È possibile definire il metodo di overload con define_overload_method
. I parametri sono il nome del metodo e un elenco di procedure. Il metodo methodname
viene creato e chiama il metodo corrispondente. Quale metodo è determinato dal numero di parametri (Non digitare!).
Una sintassi alternativa sarebbe:
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
definisce la cornice per i metodi di overload, overload_method
definisce un 'sovraccarico metodo'.
Ma, come già mentioned by Holger:
Si dovrebbe cercare di adattarsi al modo in cui Ruby. C'è una ragione per cui non c'è sovraccarico in Ruby. I metodi dovrebbero fare solo una cosa, non decidere magicamente di fare cose molto diverse solo a causa di argomenti diversi. Cerca invece di sfruttare Duck Typing e, se sei in dubbio, usa metodi diversi con nomi significativi.
Ero curioso come ho potuto implementare una versione con il tipo di sovraccarico sensibile.Eccolo:
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
Quando si chiama con
p x.ometh(1)
p x.ometh('a')
Si ottiene
"Called me with one parameter (1)"
"Called me with one string parameter (\"a\")"
Non mi piace l'opzione di lunghezza ... come args può essere passato come zero .. per lo meno questo è difficile da leggere. – Arth
Dovresti provare ad adattarti al modo Ruby. C'è una ragione per cui non c'è sovraccarico in Ruby. I metodi dovrebbero fare solo una cosa, non decidere magicamente di fare cose molto diverse solo a causa di argomenti diversi. Invece cerca di approfittare di [Duck Typing] (http://en.wikipedia.org/wiki/Duck_typing) e in caso di dubbio, usa metodi diversi con nomi significativi. –
Un'ulteriore richiesta: sovraccarico solo con il numero di parametri (come nel tuo esempio) o anche con il tipo di parametro? O in un esempio: il metodo chiama 'a (1)' e 'a ('x')' la stessa chiamata o esegue la chiamata con metodi diversi? – knut