Think of an interface as a contract.
It says:
👉 “If you want to be this type, you must do these things.”
It only defines what needs to be done, not how.
Classes that use it must provide their own implementation.
A class can implement multiple interfaces (like having multiple roles).
interface Animal {
void makeSound();
void move();
}
class Dog implements Animal {
public void makeSound() {
System.out.println("Woof!");
}
public void move() {
System.out.println("Running on four legs...");
}
}
Here:
Animal is the contract.
Dog promises to follow the contract by defining both makeSound() and move().
An abstract class is like a half-built house.
It provides:
Some ready-made parts (concrete methods).
Some empty rooms you must finish (abstract methods).
You cannot create an object of an abstract class directly.
abstract class Animal {
public void eat() {
System.out.println("Eating food...");
}
public abstract void makeSound();
}
class Cat extends Animal {
public void makeSound() {
System.out.println("Meow!");
}
}
Here:
Animal already has an eat() method for all animals. Every animal eats so you dont need to rewrite eat method for Animals.
But it leaves makeSound() blank, so each subclass (like Cat, Dog) fills it in differently.
Here’s the simple rule of thumb 👇
✅ Use Interface when:
You want to define a role/capability.
Example: Runnable (a class "can run"), Comparable (a class "can compare").
Classes may be completely unrelated but still share the same behavior.
✅ Use Abstract Class when:
You want to create a base class with some shared implementation.
Example: All animals eat and sleep the same way, but sound is different.
Classes are in the same family (like Animal → Dog, Cat).
Imagine we are building a transport app like Uber 🚖.
We have different types of vehicles: Car, Bike, Truck, ElectricCar.
🚦 Interface Example: "Drivable"
Here, not all vehicles are the same (a bike is very different from a truck).
But they all share a common ability: they can drive.
So, we make an interface:
interface Drivable {
void drive();
}
Then each vehicle defines how it drives:
class Car implements Drivable {
public void drive() {
System.out.println("Driving a car on the road...");
}
}
class Bike implements Drivable {
public void drive() {
System.out.println("Riding a bike...");
}
}
class Truck implements Drivable {
public void drive() {
System.out.println("Driving a heavy truck...");
}
}
👉 Here, the interface ensures all vehicles can "drive,"
but each vehicle has its own unique driving style.
Now, think deeper:
All vehicles have wheels, fuel type, and a start() method.
Instead of repeating this code in every class, we create an abstract class.
abstract class Vehicle {
String fuelType;
public void start() { // common implementation
System.out.println("Starting the vehicle...");
}
public abstract void refuel(); // must be defined differently
}
Concrete classes extend it:
class Car extends Vehicle {
public Car() {
fuelType = "Petrol";
}
@Override
public void refuel() {
System.out.println("Refueling the car with " + fuelType);
}
}
class ElectricCar extends Vehicle {
public ElectricCar() {
fuelType = "Electric";
}
@Override
public void refuel() {
System.out.println("Charging the electric car...");
}
}
👉 Here, the abstract class gives a common base (start() method, fuelType variable).
But still enforces subclasses to define their own refuel logic.
Interface (Drivable) = Focuses on the ability ("This thing can drive").
Abstract Class (Vehicle) = Focuses on the blueprint with shared logic (all vehicles start the same way, but refueling differs).
Think of it like this:
Interface → A driving license 🚦. Anyone who has it can drive, but how they drive depends on the person.
Abstract Class → A base car model 🚗. All cars have wheels and engines, but each brand customizes features differently.
Interface = Only contract, no common implementation.
Abstract Class = Contract + shared code.
Use interfaces for capabilities.
Use abstract classes for related objects with shared behavior.
Q1: Can a class use both?
👉 Yes! A class can extend an abstract class and implement multiple interfaces.
Q2: Which one should I prefer in modern Java?
👉 Prefer interfaces for flexibility. Use abstract classes when you need shared code or state.
Q3: Why can’t we just always use interfaces?
👉 Because interfaces don’t hold shared state (like variables) or full method implementations (except default methods). Abstract classes handle that better.
✨ That’s it! Next time you’re stuck choosing between an interface and an abstract class, just ask yourself:
“Do I need only a contract?” → Go with Interface.
“Do I need a base class with shared logic?” → Go with Abstract Class.
0
6
0