Saturday, 7 June 2014

Covariant Method Overriding of Java 5 - Coding Best Practices

Sometime knowledge of a specific Java feature can improve code quality, Covariant method overriding is one of such feature. Covariant method overriding was introduced in Java 5, but it seems it lost between other more powerful features of that release. Surprisingly not many Java programmer knows about Covariant overriding, including myself, until I read, one of the best Java book on Collection framework, Java Generics and Collection. Covariant method overriding helps to remove type casting on client side, by allowing you to return subtype of actually return type of overridden method. Covariant overriding can be really useful, while overriding methods which returns object e.g. clone() method. Since clone() return object every client needs to cast on to appropriate subclass, not any more. By using Java 5 covariant overriding, we can directly return subtype instead of object, as we will seen in examples of this article. This feature is not a star feature like Generics or Enum, but it's definitely something worth knowing, given overriding methods are integral part of Java programming. I have discussed a bit about this feature earlier in difference between overriding and overloading article, and here I will show couple of more examples to justify it's usage.



Covariant Method Overriding Example

As I said, one of the best example of this is overriding clone() method, which is declared in java.lang.Object class and has a return type of Object. If you have used java.util.Date in your project and has called it's clone method to make a copy, you might know that you need to cast it back to Date as shown below :

Date d = new Date();
Date clone = (Date) d.clone();

wouldn't it be great if clone() method can return Date instead of Object? Well it can from Java 5 onwards, but unfortunately code in java.util.Date is not yet updated to take advantage of this, at least till Java 6. Now let's create our own class and override clone() method to demonstrate use of covariant method overriding in Java.

import java.util.Date;

/** 
  * Java program to demonstrate how to use covariant method overriding to avoid
  * casting at client side.
 
  * @author http://learn-about-linux.blogspot.com
  */
public class CovariantMethodOverridingTest {

    public static void main(String args[]) {
      
        //without covariant overriding, cast at client side needed
        Date d = new Date();
        Date clone = (Date) d.clone();  //casting required
       
        //with covariant method overriding, no client side cast
        Duck duck = new Duck(0xFFFFFF);
        Duck copy = duck.clone(); //no casting
    }

  
}

class Duck implements Cloneable{
    private int color = 0xFFFFFF;
   
    public Duck(int color){
        this.color = color;
    }
   
    public int getColor(){
        return color;
    }

    @Override
    protected Duck clone() {
        Duck clone = null;
        try{
            clone = (Duck) super.clone();
           
        }catch(CloneNotSupportedException ex){
            throw new RuntimeException(ex);
        }
       
        return clone;
    }  
   
}

You can see in our test program, we don't need to type cast object returned from clone() method to Duck, because instead of java.lang.Object, its returning java.util.Date. This is also obvious from looking at overriding clone() method in Duck class, you can see its return type is Duck, and not Object. In fact, if you have implemented your own Comparator or Comparable in Java, you can also see that their compare() and compareTo() directly return the type specified in Type parameter instead of object. Though this looks a very small and subtle change, it's impact is huge. I am sure they will implement clone() method of java.util.Date sooner or later to take advantage of this feature, unless they decide to deprecate it in favour of new Date and Time API coming in Java 8.


That's all on covariant method overriding of Java 5 guys. Always take advantage of this feature, while overriding method in Java 5, 6 ,7 and very soon on Java 8. You can return any subtype, based upon your need. All other rules of method overriding remains same. I know Java is vast, and there are many more features like this, which can be really handy on day to day job but many times remains hidden from large number of Java developers. I also suggest reading Java Generics and Collection, a must read book for any senior Java developer. I always remain in search for hidden gems of Java programming language, API or third-party library which can make your task easy, can improve code quality and add value by any means. If you come across any such feature, which you like to share with us, go ahead and comment about it.

Related articles for further reading
Difference between static and dynamic binding in Java
Method Overloading best practices in Java
Difference between bounded and unbounded wildcards in Generics

No comments:

Post a Comment