top of page
Search

How to Choose Between Interface and Abstract Classes in Java

  • Writer: Anant Mishra
    Anant Mishra
  • Aug 19, 2023
  • 3 min read

Updated: Aug 27, 2023

In Java, we have interfaces and abstract classes. When it comes to choosing which one, we give arguments like choosing interfaces that support multiple inheritances or choosing an abstract class that provides the implementation of a few methods in your parent class (though from Java 8 onward, we can give default method implementation in interface also). Visit when-to-use-abstract-class-and-interface for more details.

This is a famous and basic interview question related to core Java, and the explanation above holds true.


Why Do We Need a 100 Percent Abstract Class?

Now, this question is really important, because based on the above explanations, a 100 percent abstract class is not at all useful, because it doesn't provide a default implementation of methods nor does it support multiple inheritances.

So can we say that we should never create a 100% abstract class, or we are missing something here?

Let’s dive deeper to understand this better. We will take the example of creating a car and decide which interfaces and abstract classes are required.


What Is an Abstract Class?

Abstract means that something is not fully concrete — it’s merely an idea or gist of something. So when we talk about abstract classes, it means a class that does not have a concrete implementation in itself. This is just a structure or guideline created for other concrete classes. We can say that an abstract class is the soul of a concrete class. This is the reason we “extend” abstract classes. An abstract class should only have those properties and methods, without which a concrete class can't exist.

This is the reason Java does not support multiple inheritances for abstract classes. Because one concrete class can behave (or take all properties) of only one abstract class (and obviously, a body can’t have two souls).

For example, Man and Car have many common behaviors, like movement, creating sound, etc., but a Car class can only behave like a Vehicle, not as a human, and the Man class can only behave like a human, not a vehicle.

I agree that the above example is lame, but even in real life scenarios, if you are not sure which abstract class you should inherit or you think there is a need to inherit more than one abstract class, then this is a design smell, and you should revisit the design of your project.

Based on what we have discussed above, we need to create a Vehicle abstract class. This abstract class will have properties like Engine, Shape, etc. of Car and related methods. We added Engine and Shape in the abstract class because no vehicle can exist without these two.

abstract class Vehicle {
  private String engine;
  abstract void startEngine();
  abstract void stopEngine();
}

What Is an Interface?

An interface is a behavioral contract between different systems. In Java interfaces, we define the behavior of a class, which will implement this interface. One class can have a number of different behaviors, that is why Java allows us to “implement” N number of interfaces. Interfaces are meant to provide only behaviors. This is why the Java naming convention suggests using adjectives as the name of an interface.

For example, a car can move, so we can create a movable interface and implement it in our Carclass. It is the same for drift and honk behavior. These are the behaviors of the Carmethod, not inbuilt properties. A Car will be car, even if it is not able to move.

interface Movable { 
  void move();
}

The sad thing is that we are habitual of using interfaces at the level where we nearly forget the power of abstract classes, their use, and the intention behind creating them.


Dummy Java Code Related to Car Class Creation


class Car extends Vehicle implements Movable {
  @Override
  void startEngine() {
    System.out.println("starting car's engine");
  }
  @Override
  void stopEngine() {
    System.out.println("stoping car's engine");
  }
​
  @Override
  public void move() {
    System.out.println("moving car");
  }
}

Summary

Key takeaways related to abstract class creation:

  • Create an abstract class when you are providing guidelines for a concrete class.

  • Abstract class creation is not at all related to whether you want to provide the implementation of any method or not.

  • Add only those properties and behaviors to the abstract class, without which your concrete class will lose its existence. For example, the Vehicle cannot exist without an engine.

Key takeaways related to interface creation:

  • Create interfaces that provide additional behavior to your concrete class. When we share these interfaces to the external system, then it becomes a contract, that is why we say that interfaces are behavioral contracts of the concrete class.

  • These behaviors should not be mandatory for your class. These behaviors should add more capabilities to your class. For example, a Car will be a Car, even if it cannot move.

  • Ask the question, whenever a concrete class will implement your interface, will it require all behaviors mentioned in your interface, or only a few? Refactor your interfaces in multiple interfaces, until the answer to the above question is yes.

Thanks for reading!

 
 
 

Comments


bottom of page