Unit 13: Overloading
Learning Objectives
Students should
- understand what is overloading.
- understand how to create overloaded methods.
Method overloading
In the previous unit, we introduced method overriding. That is, when a subclass defines an instance method with the same method descriptor as an instance method in the parent class.
In contrast, method overloading is when we have two or more methods in the same class (or inherited from superclass) with the same name but a differing method signature1. In other words, we create an overloaded method by changing the type, order, and number of parameters of the method but keeping the method name identical.
Lets consider an add
method which allows us to add two numbers, and returns the result. What if we would like to create an add
method to sum up three numbers?
1 2 3 4 5 6 7 |
|
In the example above, the methods add(int, int)
and add(int, int, int)
are overloaded. They have the same name but a different number of parameters. We can see that this allows us to write methods to handle differing inputs.
Now lets consider our Circle
class again. Our Circle::contains(Point)
method allows us to check if a Point
is within the radius of the current instance of the Circle
. We would like to create a new method Circle::contains(double, double)
which will allow us to check if an x
and y
coordinate (another valid representation of a point) is within our circle.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
|
In the above example, Circle::contains(Point)
and Circle::contains(double, double)
are overloaded methods.
Recall that overloading requires changing the order, number, and/or type of parameters and says nothing about the names of the parameters. Consider the example below, where we have two contains
methods in which we swap parameter names.
1 2 3 4 5 6 7 8 9 |
|
These two methods have the same method signature, and therefore contains(double, double)
and contains(double, double)
are not distinct methods. They are not overloaded, and therefore this above example will not compile.
1 2 3 4 |
|
As it is also a method, it is possible to overload the class constructor as well. As in the example below, we can see an overloaded constructor which gives us a handy way to instantiate a Circle
object that is the unit circle centred at origin.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
1 2 3 4 |
|
It is also possible to overload static
class methods in the same way as instance methods. In the next unit, we will see how Java chooses which method implementation to execute when a method is invoked.
Overriding vs Overloading
Properties | Overriding | Overloading |
---|---|---|
Same method name | ||
Same method signature | ||
In the same class | ||
In the subclass |
Note that the last point is quite subtle. This is because the subclass inherits all the method from the superclass. As such, in the following example, we still have overloading.
1 2 3 4 5 6 7 |
|
Chaining Constructor
If we look at the call to overloaded constructor new Circle()
, it is equivalent to new Circle(new Point(0, 0), 1)
. Recap the spirit of abstraction
"Each significant piece of functionality in a program should be implemented in just one place in the source code. Where similar functions are carried out by distinct pieces of code, it is generally beneficial to combine them into one by abstracting out the varying parts."
In the spirit of abstraction, we may want our overloaded constructor Circle::Circle()
to invoke our original constructor Circle::Circle(Point, double)
. That way, any changes will have to be made in only one place. This can be achieved by invoking this(..)
as the first line on the constructor. So, our Circle
class can be written as follows.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
If there are more constructors, we can have more chaining. We may want to chain from the "simpler" constructor to the more "complex" constructor. Consider adding another overloaded constructor that allows specifying a radius but will always be centred at origin.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
Remember how we mentioned that the call to super(..)
(if any) in the constructor must be the first line in the constructor? The call to this(..)
(if any) must also be the first line in the constructor. Therefore, you cannot have both call to super(..)
and call to this(..)
. Which also means that if there is a call to this(..)
default constructor is also not automatically added.
-
Note that this is not the same as the method descriptor. You can not overload a method by changing the return type. ↩