Bits of Java – Episode 16: Method overriding vs method hiding

Last week we started looking into the difference between method overriding and method overloading. This episode will cover, instead, the difference between method overriding and method hiding.

We will not go into all the technical details of method overriding, since we already discussed them. What's important to remember from last time is that one of the rules about method overriding stated that you cannot override a static method. Indeed, static methods can only be hidden.

But, what exactly does it mean for a method to be hidden? Well, as for overriding, you can hide a method which your class inherits from one of its super classes or from one of its interfaces. If the method in question is static you can implement your own version, through method hiding, following all the rules we have learned about method overriding, so:

  • The hiding version of the method must have the same signature of its original version (same name and same parameter list);
  • The hiding version of the method must have the same or a more permissive access modifier with respect to its original version;
  • The hiding version of the method must have the same or a less broader list of declared checked Exceptions with respect to its original version;
  • The hiding version of the method must have the same or a covariant return type with respect to its original version.

In addition to these rules, since hiding is possible only for static method, also the "new" version of the method must be static. Let's look at some examples.

In the previous example, ChildClass extends ParentClass, and so it inherits all the visible methods of its parent. Among them there is the static method myMethod. In ChildClass we hide the parent version of such method, by providing our own implementation. This is a valid implementation, since the signature is the same, the return type is also the same, the access modifier is different but more permissive with respect to the original version, and we kept the static specifier.

Let's now look at some invalid examples.

OK, so now we know how to properly hide a parent static method. If some of you followed our last post, you could ask at this point what is the difference then between overriding and hiding, a part from the fact that one is applied to non-static methods and one to static ones.

Well, the difference is precisely that! But is not just a difference in the definition; the static keyword is what makes the difference in how an hiding method behaves with respect to an overriding one. Let's try to explain it!

When we talked about the static keyword, we started our discussion by saying that static means something which is referred to the class, and not to every instance of the class. Indeed, a static class variable is a variable which is shared among all the instances of that class.

When we introduced method overriding we said that once you have your own version of a parent method in a sub class, if you call that method through an instance of the subclass the overridden version is actually called.

Then, what happens when you call printMessage, for instance, inside another inherited method that you chose not to override?

Let's look at this example. In our sub class ChildClass we override the printMessage method, but we kept the parent version of printAnotherMessage. In this method, however, there is a call to printMessage. When we call printAnotherMessage from an instance of ChildClass it enters the parent version (the only one we have) of printAnotherMessage, but then it calls the ChildClass version of printMessage.

So, here is the key point. An overridden version of a method substitute the parent version at runtime, even if the method is called inside the parent class itself!

Let's now look at a similar example, but with method hiding.

Now the two methods in the parent class are static and we are hiding just one of them, printMessage, as we did before. In the main we are calling first ChildClass.printMessage. This realizes that in our subclass ChildClass we have a new version for it, and thus it calls that one, printing "Hola Ilenia". Then, we call ChildClass.printAnotherMessage, which then needs to rely on the parent class implementation, since we do not have one in ChildClass. In printAnotherMessage there is a call to printMessage, exactly as before, but this time the method was just hidden in the sub class, not overridden, meaning that from the parent class we will call the parent class version of the method, resulting in printing "Hi Ilenia", and not "Hola Ilenia"!

So, here is the big difference! At runtime, an overridden version of a method will substitute the parent version also in the parent class, while for an hiding method this is not the case! In this sense hiding is weaker than overriding, because if you end up in the parent class implementation and from this you need to call a static method, it does not matter if you had hidden it in your sub class. You are now in the parent one, and so the parent version will be called. When you have a non-static method and you override it, instead, even if you end up in the parent implementation, it will always remember where you started from and that you had provided a different implementation for the method, and so the sub class version will be called!

This was all about method overriding vs method hiding. Next week we will talk about modules in Java!

By Ilenia Salvadori