Wednesday, September 27, 2017

When can I use Interface and Abstract class?

There is always a question of when should you go for using an interface and/or an abstract class. You may consider the below scenarios to decide.

This post won't explain what is an Interface and an Abstract class or their differences rather it would explain the scenarios for the usage of these.

Scenario 1: I want to have some predefined common functionality to my child classes and also want to enforce them some contract. These contracts might be suitable for all the classes in the same hierarchical system. But, I don't think the contract(s) might be useful to other systems (classes other than this hierarchical structure) or it would make sense to them.

Solution: Use Abstract class - Define concrete methods (for predefined common functionality) and declare abstract methods (contract with child classes)

Example:
public abstract class Vehicle  {
          public abstract void startVehicle();
          public abstract void stopVehicle();
          public final void printVehicleDetails() { }
}

public class Plane extends Vehicle {
         public void startVehicle() { }
         public void stopVehicle() { }
}
public class Bicycle extends Vehicle  {
         public void startVehicle() { }
         public void stopVehicle() { }
}
Explanation: In the above example the abstract methods, startVehicle() and stopVehicle() are needed for this hierarchical system. All the Vehicles must have these details. But, it may not be useful to other systems and hence don't want to make it a generic one (interface type. Please note that interface is something which can be used by any one; its public)


Scenario 2: I want to have some common functionality to my child classes and also want to enforce them some contract. I also feel that the contract might be useful to other systems(classes other than this hierarchical structure). But, at the same time it may not be relevant to some other classes in the same hierarchical systems.

Solution: Use Interface - declare abstract methods (contract with child classes). Define concrete methods (for predefined common functionality) in the non-abstract parent class.

Example:
public interface Flight {
       public void fly();
public abstract class Vehicle {
         public abstract void fly(); //wrong to have here; this will make bicycle to fly
         public final void printVehicleDetails() { }
}

public class Plane extends Vehicle implements Flight {    
         public void fly() { }
}
public class Helicopter extends Vehicle implements Flight {
         public void fly() { }
}
          public class Bicycle extends Vehicle {
          }

Explanation: In this example you can not have abstract method fly() in your abstract parent class, as it would lead to different behavior to other child classes like Bicycle; these can't fly. Hence, move this fly() behavior to an Interface and use it in the child classes like Plane, Helicopter where it is relevant.


Scenario 3: Combination of Scenario 1 and 2. I want to have
  • Common functionality to the child classes
  • Some contracts which are suitable for all the classes in the same hierarchical systems, but may not be useful outside the same hierarchical systems (candidate for Abstract class)
  • Some contracts which may not be relevant to all the classes in the same hierarchical systems, but, might be useful outside this hierarchical system (candidate for Interface)
Solution: Abstract class and Interface

Example:
public interface Flight {
       public void fly();
public abstract class Vehicle {
         public abstract void startVehicle();
         public abstract void stopVehicle();
         public final void printVehicleDetails() { }
}

public class Plane extends Vehicle implements Flight { //start(), stop(), and fly()  
         public abstract void startVehicle() { }
         public abstract void stopVehicle() { }
         public void fly() { }
}
public class Helicopter extends Vehicle implements Flight { //start(), stop(), and fly()
         public abstract void startVehicle() { }
         public abstract void stopVehicle() { }
         public void fly() { }
}
          public class Bicycle extends Vehicle { //will have only start() and stop()
                   public abstract void startVehicle() { }
                   public abstract void stopVehicle() { }
          }

Explanation:
In the above example the concrete methods startVehicle(), and stopVehicle() are suitable for all the Vehicle types. Hence, you can accommodate into an Abstract class. But, the fly() abstract method is not relevant to all the Vehicle types. Hence, move this behavior to an Interface.

Do you know - Series - 4: Boxing and Unboxing - Integer assignment and comparison

We know about boxing and unboxing in Java. It is about automatic conversion of primitive type value into its Wrapper Object equivalent type...