Object-Oriented Programming in Java

Inheritance & Polymorphism


Module III: Inheritance and Polymorphism. This module introduces how classes can reuse and extend existing functionality, and how Java resolves overridden methods at runtime. These concepts are central to object-oriented programming.


Understanding Inheritance

Inheritance lets a class (subclass) acquire the properties and methods of another class (superclass). It promotes code reuse and logical hierarchy.

  • Superclass – the class whose features are inherited
  • Subclass – the class that extends the superclass
  • extends keyword is used for inheritance
  • Java supports single inheritance of classes
Simple Inheritance Example
class Animal {
  void eat() { System.out.println("eating"); }
}

class Dog extends Animal {
  void bark() { System.out.println("barking"); }
}

Dog d = new Dog();
d.eat();   // inherited
d.bark();  // own method

Diagram: inheritance-tree-basic.png


Using the super Keyword

The super keyword is used to access superclass members: fields, methods, and constructors.

class Person {
  String name;
  Person(String name) {
    this.name = name;
  }
}

class Student extends Person {
  int roll;
  Student(String name, int roll) {
    super(name);       // calling superclass constructor
    this.roll = roll;
  }
}

Diagram: super-call-flow.png


Multilevel Hierarchy

In multilevel inheritance, a subclass becomes a superclass for another class. Java supports **multilevel** but not **multiple** inheritance of classes.

class A { }
class B extends A { }
class C extends B { }     // A -> B -> C

Diagram: multilevel-hierarchy.png


Method Overriding

When a subclass declares a method with the same name and signature as the superclass method, it is called overriding.

  • Used to provide specific implementation
  • Must have same method name, return type and parameters
  • Only instance methods can be overridden
class Shape {
  void draw() { System.out.println("drawing shape"); }
}

class Circle extends Shape {
  void draw() { System.out.println("drawing circle"); } // override
}

Dynamic Method Dispatch (Run-time Polymorphism)

Runtime polymorphism determines the method to execute based on the actual object type, not reference type.

Shape s = new Circle();  // reference of Shape, object of Circle
s.draw();                 // calls Circle's draw (runtime)

Diagram: dynamic-dispatch.png


final Keyword with Inheritance

  • final class – cannot be inherited
  • final method – cannot be overridden
final class Constants { }       // cannot be extended
class A {
  final void show() { }
}

The Object Class

Every Java class implicitly extends Object, the root of the class hierarchy. Important methods include:

  • toString() – returns string representation
  • equals() – compares two objects
  • hashCode()
  • getClass()
class Demo { }

Demo d = new Demo();
System.out.println(d.toString());
System.out.println(d.getClass());