18. The Four Pillars of OOP
Object-oriented programming rests on four pillars: encapsulation, inheritance, polymorphism, and abstraction โ each with a distinct purpose and Java mechanism.
Java 21 (core language)Explanation
Encapsulation: bundling state and behaviour together and restricting direct access to state via access modifiers (private fields + public getters/setters or records). Goal: protect invariants and allow implementation changes without breaking callers.
Inheritance: a subclass inherits fields and methods from a superclass using extends. Enables code reuse and establishes an "is-a" relationship. Java supports single-class inheritance but multiple interface implementation.
Polymorphism: a single interface or supertype can refer to objects of different subtypes. At runtime the actual subtype's method is called (dynamic dispatch / virtual dispatch). The most powerful form in Java is method overriding + upcasting.
Abstraction: hiding implementation details and exposing only what callers need. Achieved through abstract classes (partial implementation) and interfaces (pure contract). Records and sealed types add structured abstraction for data modelling.
Example
public class FourPillars {
// ENCAPSULATION: private state + controlled access
static class BankAccount {
private double balance;
BankAccount(double initialBalance) { this.balance = initialBalance; }
public double getBalance() { return balance; }
public void deposit(double amount) {
if (amount <= 0) throw new IllegalArgumentException("Amount must be positive");
balance += amount;
}
}
// ABSTRACTION: interface exposes contract, hides implementation
interface Drawable { void draw(); }
// INHERITANCE: Dog extends Animal
static class Animal {
String name;
Animal(String name) { this.name = name; }
String sound() { return "..."; }
}
// POLYMORPHISM: subclass overrides sound()
static class Cat extends Animal implements Drawable {
Cat(String name) { super(name); }
@Override String sound() { return "Meow"; }
@Override public void draw() { System.out.println("Drawing a cat ๐ฑ"); }
}
static class Dog extends Animal implements Drawable {
Dog(String name) { super(name); }
@Override String sound() { return "Woof"; }
@Override public void draw() { System.out.println("Drawing a dog ๐ถ"); }
}
public static void main(String[] args) {
// Encapsulation
BankAccount acc = new BankAccount(100);
acc.deposit(50);
System.out.println("Balance: " + acc.getBalance());
// Polymorphism โ Animal reference, Dog/Cat objects
Animal[] animals = { new Dog("Rex"), new Cat("Whiskers") };
for (Animal a : animals) {
System.out.println(a.name + " says " + a.sound()); // dynamic dispatch
}
// Abstraction โ Drawable reference
Drawable[] drawables = { new Dog("Fido"), new Cat("Luna") };
for (Drawable d : drawables) d.draw();
}
}Sources
- https://docs.oracle.com/javase/tutorial/java/concepts/ โ Java OOP concepts tutorial
- https://dev.java/learn/oop/ โ OOP fundamentals on dev.java