CHAPTER-8 Java Inheritance - Examples

Here are 5 Java inheritance programs demonstrating single, multilevel, hierarchical, multiple (via interfaces), and hybrid inheritance, showing how classes reuse and extend functionality, like vehicles, animals, or shapes, to build complex systems efficiently.

1. Single Inheritance
2. Multilevel Inheritance (Animal Chain)
3. Hierarchical Inheritance (Shapes)
4. Multiple Inheritance (Using Interfaces: Flying Pet).
5. Hybrid Inheritance (Mix: Class(Animal) + Interface(Pet)) Combines multilevel .
6. Method Overriding in Java Inheritance Example.
7. DynamicBinding in Java Inheritance Example .

1. Single Inheritance (Vehicle Example)

// Superclass
class Vehicle {
    void start() { System.out.println("Vehicle starting..."); }
}

// Subclass
class Truck extends Vehicle {
    void drive() { System.out.println("Truck is driving."); }
}

// Main class to test
public class SingleInheritanceDemo {
    public static void main(String[] args) {
        Truck myTruck = new Truck();
        myTruck.start(); // Inherited from Vehicle
        myTruck.drive(); // Own method
    }
}
 
Output:
Animal is eating. Dog is barking. Pug is fetching.
2. Multilevel Inheritance (Animal Chain)

Dog class inherits from Animal, and Pug class inherits from Dog.


	
// Grandparent class
class Animal {
    void eat() { System.out.println("Animal is eating."); }
}

// Parent class (inherits from Animal)
class Dog extends Animal {
    void bark() { System.out.println("Dog is barking."); }
}

// Child class (inherits from Dog)
class Pug extends Dog {
    void fetch() { System.out.println("Pug is fetching."); }
}

// Main class to test
public class MultilevelInheritanceDemo {
    public static void main(String[] args) {
        Poodle myPug = new Pug ();
        myPug.eat();  // From Animal
        myPug.bark(); // From Dog
        myPug.fetch(); // From myPug
    }
}

	
	
C:\java>java MultilevelInheritanceDemo 
Animal is eating.!!
Dog is barking.
Pug is fetching.
3. Hierarchical Inheritance (Shapes)

Circle and Rectangle both inherit from Shape.



// Superclass
class Shape {
    void display() { System.out.println("This is a shape."); }
}

// Subclass 1
class Circle extends Shape {
    void drawCircle() { System.out.println("Drawing a circle."); }
}

// Subclass 2
class Rectangle extends Shape {
    void drawRectangle() { System.out.println("Drawing a rectangle."); }
}

// Main class to test
public class HierarchicalInheritanceDemo {
    public static void main(String[] args) {
        Circle c = new Circle();
        c.display(); // From Shape
        c.drawCircle();

        Rectangle r = new Rectangle();
        r.display(); // From Shape
        r.drawRectangle();
    }
}

 
	

Output:

This is a shape.
Drawing a circle.
This is a shape.
Drawing a rectangle.

4. Multiple Inheritance (Using Interfaces: Flying Pet) In this scenario, the Computer class acquires the properties of both Workable and Playable, allowing a single object to have multiple types and behaviors.
Why Not Multiple Class Inheritance?
In Java, a class cannot extend into more than one class. Multiple Inheritance can be implemented only with an interface.
 
// Define the first interface
interface Workable {
    void work(); // Abstract method
}

// Define the second interface
interface Playable {
    void play(); // Abstract method
}

// The class implements both interfaces
class Computer implements Workable, Playable {
    @Override
    public void work() {
        System.out.println("Workable");
    }

    @Override
    public void play() {
        System.out.println("Playable.");
    }
}

// Main class to test the implementation
public class TestMultipleInheritance {
    public static void main(String[] args) {
        Computer myComputer = new Computer();
        myComputer.work();
        myComputer.play();
    }
}

Output:
Workable.
Playable.

5. Hybrid Inheritance (Mix: Class(Animal) + Interface(Pet)) Combines multilevel .

Animal class is inherited by a Dog class (single inheritance), and the Dog class also implements an interface called Pet (multiple inheritance via interface).


 // Parent Class (Hierarchical Base)
class Animal {
    void eat() {
        System.out.println("Animal eats food");
    }
}

// Interface (used to achieve multiple inheritance behavior)
interface Pet {
    void play();
}

// Hierarchical Child 1 / Multilevel Intermediate
class Dog extends Animal implements Pet {
    void bark() {
        System.out.println("Dog barks");
    }

    // Implementing the Pet interface method
    @Override
    public void play() {
        System.out.println("Dog plays with a ball");
    }
}

// Hierarchical Child 2
class Cat extends Animal {
    void meow() {
        System.out.println("Cat meows");
    }
}

// Main class to demonstrate the hybrid inheritance
public class HybridInheritanceExample {
    public static void main(String[] args) {
        // Dog object can access Animal methods and Pet methods
        Dog myDog = new Dog();
        myDog.eat();    // Accessing method from Animal class
        myDog.bark();   // Accessing method from Dog class
        myDog.play();   // Accessing method from Pet interface

        System.out.println("\n---");

        // Cat object can access Animal methods
        Cat myCat = new Cat();
        myCat.eat();    // Accessing method from Animal class
        myCat.meow();   // Accessing method from Cat class
    }
}

Explanation of the Hybrid Structure

  • Hierarchical Inheritance: Both Dog and Cat classes inherit from the single parent class Animal. This forms a hierarchy.
  • Single Inheritance: The Dog class extends only one class (Animal).
  • Multiple Inheritance (via Interface): The Dog class implements the Pet interface, allowing it to have behaviors from two different sources (Animal class and Pet interface).

Output:

Animal eats food
Dog barks
Dog plays with a ball

---
Animal eats food
Cat meows
6. Method Overriding in Java Inheritance Example

The following example demonstrates method overriding with Animal and Cow classes. Both classes have a showInfo() method, but the Cow class provides its own specific implementation.


 // Parent class (Superclass)
class Animal {
    // Method in the superclass
    public void showInfo() {
        System.out.println("I am an animal.");
    }
}

// Child class (Subclass)
class Cow extends Animal {
    // Overriding the displayInfo() method of the superclass
    @Override
    public void showInfo() {
        System.out.println("I am a cow.");
    }
}

// Main class to run the example
public class MethodOverriding {
    public static void main(String[] args) {
        Cow c1 = new Cow();
        // Calls the overridden method in the Cow subclass
        c1.showInfo();
    }
}

Output:
I am a cow.
In this code:

  • Cow extends Animal, establishing an "IS-A" relationship.
  • The showInfo() method in Cow has the exact same signature (name, return type, and parameters) as the method in Animal.
  • When c1.showInfo() is called, the Java runtime environment determines the actual object type at runtime and executes the subclass's method.
  • The @Override annotation is good practice; it tells the compiler that you intend to override a superclass method, helping prevent errors

Key Rules for Overriding

  • Inheritance is required: Overriding only works within an inheritance hierarchy (IS-A relationship).
  • Same Signature: The overriding method must have the same name, argument list, and return type (or a subtype) as the superclass method.
  • Access Modifiers: The access level cannot be more restrictive than the overridden method's access level. For example, a protected method in the superclass can be public in the subclass, but not private.
  • Cannot Override: final, static, or private methods cannot be overridden.
  • Constructors: Constructors cannot be overridden.
  • super Keyword: super keyword can be used to call the superclass's version of the overridden method from within the subclass.
7. DynamicBinding in Java Inheritance Example Dynamic binding in Java, also called as late binding or runtime polymorphism, is when the method call is resolved at runtime based on the actual object's type, rather than the reference variable's type. This is most clearly demonstrated through method overriding

	
class Shape {
    public void draw() {
        System.out.println("Drawing a shape");
    }
}

class Circle extends Shape {
    @Override
    public void draw() {
        System.out.println("Drawing a Circle");
    }
}

public class DynamicbindingDemo{
    public static void main(String[] args) {
	
		// Create a reference variable of type Shape, but point it to a Circle object
	Shape shape = new Circle();
	shape.draw(); // Output: Drawing a Circle		
    
    }
}

Output:
Drawing a Circle.
Explanation

  • Reference Type vs. Object Type: The variable shape is declared as a Shape type reference. However, it holds an actual instance of a Circle object.
  • Compile Time: At compile time, the Java compiler sees a Vehicle reference and ensures that the Vehicle
  • class has a draw() method (which it does). The compiler doesn't know exactly which version of the method will run.
  • Runtime: When the program runs, the Java Virtual Machine (JVM) determines the actual type of the object being referenced, which is Circle. Because the draw() method is overridden in the Circle subclass, the JVM dynamically binds the call to the Circle class's specific implementation of the draw() method

Methods declared as private, static, or final are resolved using static binding at compile time, not dynamic binding.