You can try metaprogramming to achieve your goal.
See the following code:
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)
You can define your overloaded method with define_overload_method . Parameters are the name of the method and the list of procedures. The methodname method is methodname and calls the corresponding method. Which method is determined by the number of parameters (not type!).
Alternative syntax:
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 defines a frame for your overloaded methods, overload_method defines one "overload method".
But as mentioned by Holger :
You should try to adapt to Ruby. There is a reason why there is no overload in Ruby. Methods should do only one thing, and not magically decide to do completely different things just because of different arguments. Instead, try using Duck Typing, and if in doubt, use different methods with meaningful names.
I was curious how I can implement a version with overload sensitive type. Here he is:
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
When you call it with
p x.ometh(1) p x.ometh('a')
You get
"Called me with one parameter (1)" "Called me with one string parameter (\"a\")"