OOP Principles: Inheritance and Polymorphism
The Family Tree of Code
Imagine you have a family. Your grandparents passed down traits to your parents. Your parents passed those traits (plus their own) to you. You share family features, but you’re also unique!
That’s exactly how Inheritance works in Java. Classes can pass down their abilities to other classes, just like families pass down traits!
1. Inheritance Fundamentals
What Is Inheritance?
Think of a parent robot that can walk and talk. Now imagine you build a child robot based on it. The child robot automatically knows how to walk and talk (it inherited those skills!) but you can also add NEW abilities like dancing!
// Parent Robot
class Robot {
void walk() {
System.out.println("Walking...");
}
void talk() {
System.out.println("Hello!");
}
}
// Child Robot inherits from Robot
class DancingRobot extends Robot {
void dance() {
System.out.println("Dancing!");
}
}
The magic word is extends! When you write extends, you’re saying: “Hey, give me everything from that class!”
Why Use Inheritance?
- Reuse code - Don’t write the same thing twice!
- Organize - Keep related things together
- Modify easily - Change parent, all children update!
2. Inheritance Types
Java supports several types of inheritance. Let’s explore them with a pet shop story!
Single Inheritance
One parent, one child. Simple and clean!
class Animal {
void breathe() {
System.out.println("Breathing...");
}
}
class Dog extends Animal {
void bark() {
System.out.println("Woof!");
}
}
graph TD A[Animal] --> B[Dog]
Multilevel Inheritance
Like a family chain: Grandparent → Parent → Child
class Animal {
void breathe() { }
}
class Mammal extends Animal {
void feedMilk() { }
}
class Dog extends Mammal {
void bark() { }
}
graph TD A[Animal] --> B[Mammal] B --> C[Dog]
Hierarchical Inheritance
One parent, MANY children!
class Animal {
void breathe() { }
}
class Dog extends Animal {
void bark() { }
}
class Cat extends Animal {
void meow() { }
}
graph TD A[Animal] --> B[Dog] A --> C[Cat] A --> D[Bird]
Note: Java does NOT support multiple inheritance with classes (one child, many parents). But you can achieve it with interfaces!
3. The super Keyword
Your Direct Line to Parent
Imagine you’re a kid and you need to ask your parent something. You’d say “Hey parent!” In Java, we say super!
super does THREE magical things:
1. Call Parent’s Constructor
class Animal {
String name;
Animal(String name) {
this.name = name;
}
}
class Dog extends Animal {
String breed;
Dog(String name, String breed) {
super(name); // Calling parent!
this.breed = breed;
}
}
2. Access Parent’s Methods
class Animal {
void makeSound() {
System.out.println("Some sound");
}
}
class Dog extends Animal {
void makeSound() {
super.makeSound(); // Parent's version
System.out.println("Woof!");
}
}
3. Access Parent’s Variables
class Animal {
String type = "Unknown";
}
class Dog extends Animal {
String type = "Canine";
void showTypes() {
System.out.println(super.type); // Unknown
System.out.println(this.type); // Canine
}
}
4. Method Overriding
Same Name, Different Dance!
Remember our dancing robot? What if the child robot wants to walk DIFFERENTLY from the parent? That’s overriding!
class Bird {
void move() {
System.out.println("Walking");
}
}
class Eagle extends Bird {
@Override
void move() {
System.out.println("Flying high!");
}
}
Rules for Overriding
| Rule | What It Means |
|---|---|
| Same name | Method name must match |
| Same parameters | Exact same inputs |
| Same or broader return | Can return same or child type |
| Can’t be more private | Access can stay same or expand |
The @Override Annotation
Always use @Override! It’s like a safety helmet - Java will warn you if you mess up!
@Override // Java checks if this really overrides
void move() {
System.out.println("Flying!");
}
5. Polymorphism
One Name, Many Forms!
“Poly” means many. “Morph” means forms. Together: MANY FORMS!
Imagine a universal remote control. You press “PLAY” and:
- TV plays a show
- Radio plays music
- DVD plays a movie
Same button, different actions! That’s polymorphism!
Two Types of Polymorphism
Compile-Time (Method Overloading) Same name, different parameters. Decided at compile time.
class Calculator {
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
}
Runtime (Method Overriding) Parent reference, child behavior. Decided when program runs!
Animal myPet = new Dog();
myPet.makeSound(); // Woof! (Dog's version)
6. Dynamic Method Dispatch
The Magic Decision-Maker
This is the SECRET SAUCE behind runtime polymorphism!
Story Time: Imagine a music festival. The stage says “Next: Artist” (that’s the reference type). But WHO actually performs? That depends on who shows up! (the actual object)
class Artist {
void perform() {
System.out.println("Performing...");
}
}
class Singer extends Artist {
@Override
void perform() {
System.out.println("Singing!");
}
}
class Dancer extends Artist {
@Override
void perform() {
System.out.println("Dancing!");
}
}
Artist performer; // The stage
performer = new Singer();
performer.perform(); // "Singing!"
performer = new Dancer();
performer.perform(); // "Dancing!"
Java decides WHICH version to call at RUNTIME! It looks at the ACTUAL object, not the reference type!
graph TD A[Artist Reference] --> B{What's the<br>actual object?} B -->|Singer object| C[Call Singer.perform] B -->|Dancer object| D[Call Dancer.perform]
7. Abstract Classes
The Blueprint That Can’t Be Built
Imagine you’re an architect. You draw a blueprint for “Vehicle”. But can you BUILD just a “vehicle”? No! You build a CAR or a BIKE - specific things!
Abstract classes are blueprints. They say “this is what you MUST have” but can’t be built themselves!
abstract class Vehicle {
String brand;
// Concrete method - has a body
void startEngine() {
System.out.println("Engine starting...");
}
// Abstract method - NO body!
abstract void drive();
}
class Car extends Vehicle {
@Override
void drive() {
System.out.println("Driving on 4 wheels!");
}
}
Key Points About Abstract Classes
- Use
abstractkeyword - Can have BOTH abstract and regular methods
- Cannot create objects of abstract class directly
- Children MUST implement abstract methods
// This is WRONG!
Vehicle v = new Vehicle(); // Error!
// This is RIGHT!
Vehicle v = new Car(); // Works!
8. Abstract Methods
The Promise Without the Action
An abstract method is like a job posting: “We need someone who can DO THIS” - but it doesn’t say HOW to do it!
abstract class Shape {
// Says "calculate area" but doesn't say HOW
abstract double calculateArea();
}
class Circle extends Shape {
double radius;
Circle(double radius) {
this.radius = radius;
}
@Override
double calculateArea() {
return 3.14159 * radius * radius;
}
}
class Rectangle extends Shape {
double width, height;
Rectangle(double w, double h) {
this.width = w;
this.height = h;
}
@Override
double calculateArea() {
return width * height;
}
}
Rules for Abstract Methods
| Rule | Example |
|---|---|
| No body | abstract void fly(); |
| Only in abstract class | Class must be abstract too |
| Must be overridden | Child class provides the body |
| Can’t be private | Others need to see it! |
The Big Picture
graph LR A[Inheritance] --> B[Reuse Code] A --> C[Types: Single, Multilevel, Hierarchical] A --> D[super keyword] E[Polymorphism] --> F[Compile-Time: Overloading] E --> G[Runtime: Overriding] G --> H[Dynamic Method Dispatch] I[Abstraction] --> J[Abstract Classes] I --> K[Abstract Methods] J --> L[Blueprint - Can't Instantiate] K --> M[Promise - No Implementation]
Quick Recap
| Concept | One-Line Summary |
|---|---|
| Inheritance | Child gets parent’s stuff using extends |
| super | Talk to your parent class |
| Override | Child changes parent’s behavior |
| Polymorphism | Same name, different actions |
| Dynamic Dispatch | Java picks the right method at runtime |
| Abstract Class | Blueprint that can’t be built |
| Abstract Method | Promise without implementation |
You Did It!
You now understand how classes can:
- Inherit from each other like families
- Override behaviors to be unique
- Transform through polymorphism
- Promise features through abstraction
These concepts are the HEART of Object-Oriented Programming. Every Java application you’ll ever build uses them!
Keep practicing, and soon you’ll be creating beautiful class hierarchies that are easy to understand, maintain, and extend!