Sunday 15 July 2018

Covariant and Contravariant

Covariant Return Type in Java

If method in the super-class has return type ref1 and the overriding method in the subclass has return type ref2 then ref2 must be the subtype of ref1. That is known as covariant return type in Java. Covariant method overriding helps to remove type casting on client side and it allows us to return subtype of actually return type of overridden method.

class Parent {

  Object getName(){}

}

class Child extends Parent {

  String getName() {}

}

Note:- Child#getName is covariant because it returns a subclass of the return type of Parent#getName



Covariant Example in java

class First {
     String name;

     First(String name) {
           this.name = name;
     }
}

class Second extends First {
     Second(String name) {
           super(name);
     }
}

class Third {
     public First getValue() {
          return new First("Object of class First");
     }
}

class Fourth extends Third {
     // overriding method, changing return type as subclass.
     public Second getValue() {
           return new Second("Object of class Second");
     }
}

public class CovariantInJava {

     public static void main(String[] args) {
           Third third = new Third();
           System.out.println("Value from class Third : " + third.getValue().name);
          
           third = new Fourth(); // now pointing to class Fourth
           System.out.println("Value from class Fourth : " + third.getValue().name);
     }
}


Contravariant type in java

Child#display is contravariant because it takes a parameter of a superclass of the parameter of Parent#display

class Parent{
  void display(String parameter)
}
class Child extends Parent{
  void display(Object parameter)
}

Example:

package com.gaurav.demo;

class Parent{
     String msg;
    
     Parent(String message){
           this.msg = message;
     }

     @Override
     public String toString() {
           return "Parent [msg=" + msg + "]";
     }
    
    
}

class Child extends Parent{
     Child(String msg) {
           super(msg);
     }

     @Override
     public String toString() {
           return "Child [msg=" + msg +"]";
     }
    
}

class Test1 {
     public Parent display(String name) {
           return new Parent("Object of class Test1 : "+ name);
     }
}

class Test2 extends Test1 {
     // overriding method, changing parameter type as parent.
     public Child display(Object name) {
           return new Child("Object of class Test2 : "+name);
     }
    
    
}

public class ContravariantInJava {
     public static void main(String[] args) {
           String name = "Gaurav";
           Test1 test1 = new Test1();
           System.out.println("Value from class Third : " + test1.display(name));
          
           Object obj = new String("Hello");
          
           Test2 test2 = new Test2(); // now pointing to class Fourth
           System.out.println("Value from class Fourth : " + test2.display(obj));
     }
}

No comments:

Post a Comment