Abstract Class vs Interface
TL;DR
- Abstract Class: Represents an “IS-A” relationship. Can have state (instance variables) and constructors. A class can extend only ONE abstract class.
- Interface: Represents a “CAN-DO” relationship (a capability). Cannot hold state (only
public static finalconstants). A class can implement MULTIPLE interfaces.
Concept
If you are modeling a Dog, an Abstract Class (Animal) makes sense because a dog is an animal. The abstract class can hold shared state like int age; and a constructor to initialize it. All animals breathe the same way, so you provide a concrete breathe() method, but force subclasses to implement makeSound().
If you also want the Dog to be serializable, you use an Interface (Serializable). An interface defines a contract or a capability. A Dog can be serializable, and a String can be serializable, even though they share no IS-A relationship. Because Java does not support Multiple Inheritance for classes to prevent the “Diamond Problem”, a class can only extend one abstract class, but it can implement 50 interfaces.
Note: Since Java 8, Interfaces can have default methods, blurring the line between the two.
Examples
// 1. ABSTRACT CLASS
// Holds state, constructors, and access modifiers.
abstract class Animal {
protected int age; // State!
public Animal(int age) { this.age = age; } // Constructor!
public void sleep() { System.out.println("Zzz..."); } // Concrete method
public abstract void makeSound(); // Forced implementation
}
// 2. INTERFACE
// Only defines capabilities. Cannot hold instance state.
interface Pet {
// Variables in interfaces are implicitly public static final!
int MAX_PETS = 5;
void play(); // implicitly public abstract
// Java 8 default method
default void eat() { System.out.println("Eating..."); }
}
// A class can extend ONE abstract class, but MULTIPLE interfaces.
class Dog extends Animal implements Pet {
public Dog(int age) { super(age); }
@Override
public void makeSound() { System.out.println("Woof"); }
@Override
public void play() { System.out.println("Catching frisbee"); }
}
Interview Questions
Q: If interfaces can now have default methods (Java 8), why do we still need Abstract Classes?
A: Because interfaces still cannot hold State (instance variables) and they cannot have Constructors.
If all animals share an age variable and need a constructor to initialize that age, you absolutely must use an Abstract Class. Interfaces can only hold static final constants.
Q: What is the “Diamond Problem” and how does Java solve it?
A: If a class was allowed to inherit from two abstract classes (A and B), and both classes implemented a print() method differently, which print() would the child class inherit? This ambiguity is the Diamond Problem.
Java solves this by strictly forbidding multiple inheritance for classes.
However, what if a class implements two interfaces that both provide a default print() method? The Java compiler will instantly throw a compilation error, forcing the developer to explicitly override the print() method in the child class to resolve the ambiguity manually.