Method Overloading In Ruby

Paul Nicholson
4 min readFeb 1, 2018

As most people reading this will be aware, it is naive to assume that core concepts which exist in one language are guaranteed to exist in another. As someone who spends the majority of their time developing between Ruby and C#, there have been multiple occasions when I have expected something to just magically work, only to find that it doesn’t. This could be anything from some syntactic sugar to methods built into the languages themselves (an example of this being the destructor).

The purpose here is not to come across as biased (as I can say with confidence that I don’t prefer one language over the other), but to try and give an alternate approach for anyone who faces a similar scenario. Also, “there’s more than one way to skin a cat” so don’t think that just because something isn’t supported by a particular language, there isn’t an equally efficient, or better way of achieving the same result by opting for a different approach.

So, for anyone unaware, method overloading is a concept that allows you to supply a varying number of arguments, or varying types of argument to a method and the method will act accordingly based on the supplied arguments (or ‘signature’ if you will).

In C# this is achieved by writing multiple methods for each possible combination of arguments you expect that method to receive. For example;

In the Customer Class, there are three static methods called DisplayInfo. But the number of arguments differ for each.

Calling this method with a varying number of arguments will cause the output to be different, as you can see below;

C#Customer.DisplayInfo("John");
# Their name is John
Customer.DisplayInfo("John", "Smith");
# Their name is John Smith
Customer.DisplayInfo("John", "Smith", "j.smith@medium.com");
# Their name is John Smith and their email address is j.smith@medium.com

Now whilst Ruby does not support overloading methods, a similar level of functionality can still be achieved using simple conditionals. So, if you were going to take this approach in Ruby you would probably want to do the following;

As you may or may not be aware, the * which prefaces the argument variable, implies that there are potentially multiple arguments being passed to that method. We then build on this with the inclusion of a simple case statement to perform a specific action based on the number of arguments which have been passed to the method. Now calling this method with a varying number of arguments will output the below;

RubyCustomer.display_info "John"
# Their name is John
Customer.display_info "John", "Smith"
# Their name is John Smith
Customer.display_info "John", "Smith", "j.smith@medium.com"
# Their name is John Smith and their email address is j.smith@medium.com

Now, whilst this does give you the ability to overload methods based on the number of arguments. It doesn’t allow you to overload based on the type of argument being passed in. So, going back to C#, we will add a fourth method but instead of the third argument expecting a string, we make it expect an integer.

There are now two methods which accept three arguments. So, if we were to call these methods again with a valid set of arguments for each, the following would be output.

C#Customer.DisplayInfo("John");
# Their name is John
Customer.DisplayInfo("John", "Smith");
# Their name is John Smith
Customer.DisplayInfo("John", "Smith", "j.smith@medium.com");
# Their name is John Smith and their email address is j.smith@medium.com
Customer.DisplayInfo("John", "Smith", 34);
# Their name is John Smith and they are 34 years old

However, if we were to pass an integer as the third argument to our Ruby method in it’s current form. The following would be returned;

RubyCustomer.display_info "John", "Smith", 34
# Their name is John Smith and their email address is 34

Obviously, this is incorrect and the reason for this should be pretty apparent. Currently our Ruby method is only checking the number of arguments passed into the method, but not the type. To, achieve this in Ruby, we would need to update our method to also expect an integer as the third argument. We can achieve this with the following;

We have now added an additional case statement which gets hit when there are 3 arguments passed to the display_info method. However, this new case statement checks the type of the object being passed in as the third argument. By calling “.class.name ” on this argument, the type is returned. Remember that pretty much everything in ruby is an object (even nil), so as long as a third argument exists, we can obtain it’s class.

As you should be able to see from the case statement, if the third argument passed to the method is a string, it will print one thing, if the third argument is an integer, it will print something different (please note, I added ‘Fixnum’ to the case statement as prior being deprecated in to Ruby 2.4, ‘Fixnum’ will have been returned).

Now, if we call our display_info method again, but now pass an in integer as our third argument as opposed to a string. A different message will be displayed.

RubyCustomer.display_info "John", "Smith", "j.smith@medium.com"
# Their name is John Smith and their email address is j.smith@medium.com
Customer.display_info "John", "Smith", 34
# Their name is John Smith and they are 34 years old

Whilst the recurring use of case statements is far from ideal. This does allow us to achieve a similar level of functionality as seen with method overloading in other languages.

--

--