Interface vs Abstract Class
Interface vs Abstract Class
Now that you know what both tools look like, the practical question is: which one do I reach for? The answer comes down to two different relationships: what a type IS versus what a type CAN DO.
The Core Distinction
An abstract class models an is-a relationship. It represents a genuine parent type that shares state and behaviour with its children. An interface models a can-do (or behaves-like) relationship. It declares a capability that any unrelated class can choose to adopt.
- A
Dogis anAnimal— use an abstract class. - A
Dogcan beTrainable— use an interface. - A
Robotcan also beTrainable, even though aRobotis not anAnimal.
Key Technical Differences
Beyond the conceptual model, there are hard rules that constrain your choice:
- Multiple inheritance: Java allows a class to implement many interfaces but extend only one abstract class. This single limitation is the most common reason to prefer interfaces.
- Instance state: Abstract classes can have instance fields (stored state). Interfaces can only have
public static finalconstants — they carry no per-object data. - Constructors: Abstract classes can define constructors to initialise shared fields. Interfaces have no constructors.
- Access modifiers: Abstract class members can be
private,protected, orpublic. Interface members arepublicby default (thoughprivatehelper methods were added in Java 9).
Side-by-Side Example
Consider a drawing application. A Shape is a genuine parent — it has a colour field and a shared describe() method every shape inherits. Resizable and Exportable are capabilities that only some shapes need.
Notice that Circle and Rectangle share the color field and describe() method through the abstract class — that state lives in one place. The capabilities (Resizable, Exportable) are mixed in independently, so you can add or remove them per class without touching the hierarchy.
When Shared State Forces Your Hand
If your design genuinely needs a shared mutable field, you must use an abstract class. Interfaces cannot hold it. Trying to simulate shared state through static interface constants is a code smell — constants are not the same as instance data.
The "Evolving API" Factor
If you own a library and need to add a method later, the impact differs:
- Abstract class: add a concrete method — existing subclasses inherit it for free, no breakage.
- Interface (before Java 8): adding any method would break every implementor. Java 8 introduced
defaultmethods precisely to solve this — existing implementors inherit the default automatically.
default methods for public APIs. It keeps the design flexible (multiple implementations, multiple inheritance) and you can still evolve the interface without forcing immediate updates on every implementor.
Quick Decision Guide
- Need to share instance fields across subclasses? → Abstract class.
- Need a constructor to enforce initialisation? → Abstract class.
- Want a class to inherit from multiple sources? → Interfaces (you can implement many).
- Modelling a capability that unrelated types share? → Interface.
- Publishing a library API that must stay backward-compatible? → Interface with
defaultmethods.
default method, so you do not lock callers into a single inheritance chain unnecessarily.
Summary
Abstract classes and interfaces are complementary, not competing. Use an abstract class when you need to share state or enforce a strict type hierarchy. Use an interface when you are defining a capability that diverse, unrelated classes can adopt — and remember that a single class can implement many interfaces. In practice, modern Java code leans heavily on interfaces and reserves abstract classes for cases where shared mutable state or constructor logic genuinely belongs in the parent.