Search code examples
javagenericsinheritancecovariance

Covariance in inheritance


I have a super class SheetBuilder and many sub classes that inherit this class. The super class has an abstract method that all the classes inherit.

protected abstract void printResults(String abc);

Now I want to overload the same method with a different parameter but I need to do this only for one sub class. So I changed the abstract method as below,

protected abstract void printResults(Object abc);

This way I can just implement my sub class with whatever object type I want to receive as,

Sub class impl:

protected void printResults(int abc) {
//
}

Is this the correct standard or this there any other way to achieve this?


Solution

  • protected abstract void printResults(Object abc);
    

    Now I want to overload the same method with a different parameter but I need to do this only for one sub class. So I changed the abstract method as below, Is this the correct standard or this there any other way to achieve this?

    No, Object is too wide. From the client side if you want to program by interface you will have to call this printResults(Object abc);.
    And you can put any type of instance inside.

    Besides I think you mix overriding and overloading. This is overloading and not overriding because overriding cannot change the declared arguments types :

    class Base{ 
      protected abstract void printResults(Object abc);
    }
    ...  
    class BaseImpl{
      protected void printResults(String abc) {
        ...
      }
    }
    

    Here BaseImpl has two method printResults().

    If you add @Override in the BaseImpl method, the compilation will fail as it is not the same method:

    class Base{ 
      protected abstract void printResults(Object abc);
    }
    ...  
    class BaseImpl{
    @Override
      protected void printResults(String abc) {
        ...
      }
    }
    

    To answer to your question, if void printResults(String abc) is specific to a single class, add this method only in this class.
    In this case, you could not program by interface to invoke this method as this method is specific to a class.
    But if the method is specific, it is acceptable and even sometimes desirable.

    Another way to cope with your problem would be to create a base class with a generic method which the parameter may have a distinct type according to the concrete class, use generics :

    class Base <T>{ 
      protected abstract void printResults(T abc);
    }
    ...  
    
    class BaseStringImpl<String>{
    @Override
      protected void printResults(String abc) {
       ...
      }
    }
    
    ...
    class BaseIntegerImpl<Integer>{
    @Override
      protected void printResults(Integer abc) {
       ...
      }
    }