Why doesn't ruby support method overloading?

"Overloading" is a term that simply doesn't even make sense in Ruby. It is basically a synonym for "static argument-based dispatch", but Ruby doesn't have static dispatch at all. So, the reason why Ruby doesn't support static dispatch based on the arguments, is because it doesn't support static dispatch, period. It doesn't support static dispatch of any kind, whether argument-based or otherwise.

Now, if you are not actually specifically asking about overloading, but maybe about dynamic argument-based dispatch, then the answer is: because Matz didn't implement it. Because nobody else bothered to propose it. Because nobody else bothered to implement it.

In general, dynamic argument-based dispatch in a language with optional arguments and variable-length argument lists, is very hard to get right, and even harder to keep it understandable. Even in languages with static argument-based dispatch and without optional arguments (like Java, for example), it is sometimes almost impossible to tell for a mere mortal, which overload is going to be picked.

In C#, you can actually encode any 3-SAT problem into overload resolution, which means that overload resolution in C# is NP-hard.

Now try that with dynamic dispatch, where you have the additional time dimension to keep in your head.

There are languages which dynamically dispatch based on all arguments of a procedure, as opposed to object-oriented languages, which only dispatch on the "hidden" zeroth self argument. Common Lisp, for example, dispatches on the dynamic types and even the dynamic values of all arguments. Clojure dispatches on an arbitrary function of all arguments (which BTW is extremely cool and extremely powerful).

But I don't know of any OO language with dynamic argument-based dispatch. Martin Odersky said that he might consider adding argument-based dispatch to Scala, but only if he can remove overloading at the same time and be backwards-compatible both with existing Scala code that uses overloading and compatible with Java (he especially mentioned Swing and AWT which play some extremely complex tricks exercising pretty much every nasty dark corner case of Java's rather complex overloading rules). I've had some ideas myself about adding argument-based dispatch to Ruby, but I never could figure out how to do it in a backwards-compatible manner.


Method overloading can be achieved by declaring two methods with the same name and different signatures. These different signatures can be either,

  1. Arguments with different data types, eg: method(int a, int b) vs method(String a, String b)
  2. Variable number of arguments, eg: method(a) vs method(a, b)

We cannot achieve method overloading using the first way because there is no data type declaration in ruby(dynamic typed language). So the only way to define the above method is def(a,b)

With the second option, it might look like we can achieve method overloading, but we can't. Let say I have two methods with different number of arguments,

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.

So ruby needs to maintain one method in the method look up chain with a unique name.


I presume you are looking for the ability to do this:

def my_method(arg1)
..
end

def my_method(arg1, arg2)
..
end

Ruby supports this in a different way:

def my_method(*args)
  if args.length == 1
    #method 1
  else
    #method 2
  end
end

A common pattern is also to pass in options as a hash:

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'

Hope that helps


Method overloading makes sense in a language with static typing, where you can distinguish between different types of arguments

f(1)
f('foo')
f(true)

as well as between different number of arguments

f(1)
f(1, 'foo')
f(1, 'foo', true)

The first distinction does not exist in ruby. Ruby uses dynamic typing or "duck typing". The second distinction can be handled by default arguments or by working with arguments:

def f(n, s = 'foo', flux_compensator = true)
   ...
end


def f(*args)
  case args.size
  when  
     ...
  when 2
    ...
  when 3
    ...
  end
end