Inheritance, Interfaces and Polymorphism
Reuse and extend behaviour with inheritance, and program to interfaces for flexible code.
What you’ll learn
- extends, super and method overriding
- Abstract classes vs interfaces
- Polymorphism in practice
- Why "composition over inheritance" matters
Inheritance
A class can extend another class and inherit its fields and methods:
public class Vehicle {
protected final String plate;
public Vehicle(String plate) { this.plate = plate; }
public int wheels() { return 4; }
}
public class Motorbike extends Vehicle {
public Motorbike(String plate) {
super(plate); // call the parent constructor
}
@Override
public int wheels() { return 2; }
}@Override asks the compiler to verify you really are overriding a parent method — always use it.
Interfaces
An interface describes what something can do, without saying how:
public interface PaymentGateway {
Receipt charge(String customerId, long amountPaise);
}
public class RazorpayGateway implements PaymentGateway {
public Receipt charge(String customerId, long amountPaise) { /* ... */ }
}
public class StripeGateway implements PaymentGateway {
public Receipt charge(String customerId, long amountPaise) { /* ... */ }
}A class can implement many interfaces but extend only one class.
Polymorphism
Polymorphism means "one reference type, many runtime behaviours." Code written against the interface works with any implementation:
public class CheckoutService {
private final PaymentGateway gateway;
public CheckoutService(PaymentGateway gateway) {
this.gateway = gateway;
}
public Receipt pay(Order order) {
return gateway.charge(order.customerId(), order.totalPaise());
}
}CheckoutService has no idea which gateway it's using — and doesn't need to. Swap Razorpay for Stripe, or for a fake in tests, without touching this class. This exact pattern is how Spring's dependency injection works, so it's worth really understanding now.
Abstract classes vs interfaces
| Abstract class | Interface | |
|---|---|---|
| Can hold state (fields) | Yes | No (only constants) |
| Constructors | Yes | No |
| Multiple inheritance | No — one parent | Yes — many interfaces |
| Use it for | Sharing code between closely related classes | Defining a capability/contract |
Composition over inheritance
Deep inheritance trees become brittle fast. Prefer giving a class the objects it needs (composition, as CheckoutService does above) over extending classes to reuse code.
⚡ Try it yourself
Define a Shape interface with an area() method. Implement Circle and Rectangle, put a few of each in a List<Shape>, and print the total area with a single loop.
Interview questions
QWhat is the difference between overloading and overriding?+
Overloading is multiple methods with the same name but different parameter lists in the same class, resolved at compile time. Overriding is a subclass providing its own implementation of a parent method with the same signature, resolved at runtime.
QCan an interface have method implementations?+
Yes. Since Java 8, interfaces can have default and static methods, and since Java 9 private methods. They still cannot hold instance state.
Key takeaways
extendsfor one parent class,implementsfor many interfaces.- Program to interfaces so implementations can be swapped.
- Prefer composition to deep inheritance hierarchies.
Finished this lesson?
Mark it complete to move forward on your roadmap.