Overloading and overriding methods in Java

While studying Java I was introduced to the interesting concept of method overloading. Method loading seems to only exist in some languages and namely the "lower" level languages. Its main uses are to improve the readability of code by not having a number of duplicated functions that essentially do the same thing. Let's consider the example of having a simple function that adds two numbers together. Now imagine we want to have a function that adds three numbers together or four numbers together then we would have to make any number of functions again and name them, for example, addTwo addThree, addFour, right? Wrong.

public static int addStuff(int a, int b) { return a+b; }

In other languages like Python you could use optional arguments to get around this however in Java we have to look beyond all the fancy syntactical sugar and instead look at method overloading. Method overloading allows us to have multiple methods with the same name but a different implementation. This allows us to call one function that will perform different tasks depending on the context. In our example above instead of having multiple "add" methods we can instead have one named add method that behaves in a different number of ways depending on how many arguments we pass it

public class CodingChallenges { public static void main(String[] args) { System.out.println(addStuff(2)); System.out.println(addStuff(2,3)); } public static int addStuff(int a, int b) { return a+b; } public static int addStuff(int a, int b, int c) { return a+b+c; } public static int addStuff(int a, int b, int c, int d) { return a+b+c+d; } public static int addStuff(int a) { return a + a; } public static int addStuff() { return 0; } }

The flexibility here is we don't need to remember as many function names, we don't need to write more lines of documentation and in fact writing tests is easier as we only need to test one function. Calling each of these functions requires only that you vary the number of arguments that you pass it. This also works for argument types for example the two following methods will behave differently.

class MethodOverloading { private static void display(int a){ System.out.println("Got Integer data."); } private static void display(String a){ System.out.println("Got String object."); } public static void main(String[] args) { display(1); // Got Integer data. display("Hello"); // "Got a String object." } }

The way the Java Virtual Machine recognises which overloaded method is called is down to the "method signature" which is the method name combined with the method parameters. If the two methods have the same name then their method signatures will definitely different. For example, two human beings can have the same name but their signatures will definitely different. Java also uses method overloading in some seemingly inconspicuous places for example the System.out.println function is actually comprised of five different overloaded methods. Rather than memorising the printBool or printInt method we instead are presented with a single, readable method.

Methods are considered overloaded when they have the same name and have different parameters. Overloaded methods may have different returns, throw different exceptions and have different access modifiers.

Method overriding (or Runtime Polymorphism) occurs when you define a method in a child class that overrides a method in a parent class. The classic example is an Animal class can have a method called Shout which can return ${the animal} shouts however a Dog class that inherits from Animal can have the method called Shout that will return ${theDog} barks!. It is helpful to place an @Override tag at any overridden method as the compiler will point out any errors if we haven't overridden the tag correctly.

// Animal.java public class Animal { Animal(String name) { this.name = name; } public void shout(){ System.out.println(this.name + " shouts!"); } public void shout(int times) { // this method is overloaded for (int i = 0; i < int; i++) { System.out.println(this.name + " shouts!"); } } } // Dog.java public class Dog extends Animal { public Dog(String name) { super(name); } @Override public void shout() { // this method is overridden System.out.println(this.name + " barks!"); } }

A method will be considered overridden when the method name is the same and accepts the same arguments. Only methods in child classes can be overridden, constructors cannot be overridden and a subclass can use super.methodName() to call the parent's version of the overridden method.