Inheritance in Java

Inheritance in Java

On Day 9, we will dive into one of the key pillars of Object-Oriented Programming (OOPs): Inheritance. Inheritance is fundamental to OOPs as it allows a class to acquire properties and behaviors (fields and methods) from another class. This enhances code reusability, extensibility, and scalability.


1. What is Inheritance?

Inheritance is a mechanism in Java by which one class (subclass or child class) inherits the properties and behaviors (fields and methods) of another class (superclass or parent class). The subclass can use the methods and attributes of the superclass, and it can also have its own additional features.

Key Terminology:

  • Superclass (Parent Class): The class whose features are inherited.

  • Subclass (Child Class): The class that inherits features from the superclass.

  • extends keyword: Used to specify that a class is inheriting another class.


2. Why Use Inheritance?

The benefits of inheritance include:

  • Code Reusability: Instead of writing the same code in multiple places, you can define it once in the superclass and inherit it in subclasses.

  • Method Overriding: Subclasses can override the superclass’s methods to provide a specific implementation.

  • Extensibility: Subclasses can add new properties or methods while reusing the superclass’s functionality.

  • Hierarchy Creation: You can create a hierarchy of classes where each subclass represents a more specific concept than its superclass.


3. Syntax of Inheritance in Java

To inherit a class, you use the extends keyword.

Syntax:

class Superclass {
    // Fields and methods
}

class Subclass extends Superclass {
    // Additional fields and methods of subclass
}

Example:

// Superclass
class Animal {
    String name;

    public void eat() {
        System.out.println("This animal is eating.");
    }
}

// Subclass
class Dog extends Animal {
    public void bark() {
        System.out.println("The dog is barking.");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.name = "Buddy";
        dog.eat();  // Inherited method from Animal class
        dog.bark(); // Method of Dog class
    }
}

Explanation:

  • The Dog class inherits the eat() method from the Animal class, and it also has its own method bark().

  • The name attribute and eat() method are defined in Animal, but Dog can access them.


4. Types of Inheritance in Java

In Java, inheritance can take different forms:

1. Single Inheritance

  • A subclass inherits from only one superclass.

    Example:

      class Vehicle {
          // Fields and methods of Vehicle
      }
    
      class Car extends Vehicle {
          // Car inherits from Vehicle
      }
    

2. Multilevel Inheritance

  • A class can inherit from another class, which itself inherits from another class, forming a multilevel hierarchy.

    Example:

      class Animal {
          // Fields and methods of Animal
      }
    
      class Mammal extends Animal {
          // Fields and methods of Mammal
      }
    
      class Dog extends Mammal {
          // Fields and methods of Dog
      }
    

3. Hierarchical Inheritance

  • Multiple classes inherit from a single superclass.

    Example:

      class Animal {
          // Fields and methods of Animal
      }
    
      class Dog extends Animal {
          // Fields and methods of Dog
      }
    
      class Cat extends Animal {
          // Fields and methods of Cat
      }
    

Note: Java does not support multiple inheritance directly through classes, meaning a class cannot inherit from more than one class. However, multiple inheritance can be achieved using interfaces.


5. The super Keyword

The super keyword is used in inheritance to refer to the superclass. It can be used to:

  1. Call the superclass's constructor.

  2. Call the superclass’s methods that have been overridden in the subclass.

Using super to call the superclass constructor:

class Animal {
    String name;

    // Superclass constructor
    public Animal(String name) {
        this.name = name;
    }
}

class Dog extends Animal {
    // Subclass constructor
    public Dog(String name) {
        super(name);  // Calls Animal's constructor
    }

    public void displayInfo() {
        System.out.println("Dog's name: " + name);
    }
}

public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog("Buddy");
        dog.displayInfo();  // Output: Dog's name: Buddy
    }
}

Using super to call the superclass method:

class Animal {
    public void sound() {
        System.out.println("This animal makes a sound.");
    }
}

class Dog extends Animal {
    @Override
    public void sound() {
        super.sound();  // Calls Animal's sound() method
        System.out.println("The dog barks.");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.sound();
        // Output:
        // This animal makes a sound.
        // The dog barks.
    }
}

Explanation:

  • In the first example, super(name) calls the constructor of the superclass Animal to initialize the name attribute.

  • In the second example, super.sound() is used to call the sound() method of the Animal class before adding the subclass-specific behavior (barking).


6. Method Overriding

Method overriding occurs when a subclass provides a specific implementation of a method that is already defined in the superclass. The method in the subclass should have the same name, return type, and parameters as the method in the superclass.

Example of Method Overriding:

class Animal {
    public void sound() {
        System.out.println("This animal makes a sound.");
    }
}

class Dog extends Animal {
    @Override
    public void sound() {
        System.out.println("The dog barks.");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.sound();  // Output: The dog barks.
    }
}

Explanation:

  • The sound() method is overridden in the Dog class to provide a specific implementation for dogs.

  • Even though Animal defines sound(), calling it on a Dog object uses the subclass implementation.


7. Preventing Inheritance with final

You can prevent a class from being inherited by declaring it as final. You can also prevent method overriding by declaring a method final.

Final Class:

final class Animal {
    // This class cannot be inherited
}

Final Method:

class Animal {
    public final void sound() {
        System.out.println("This is a final method and cannot be overridden.");
    }
}

8. Object Class: The Root of All Classes

In Java, every class is implicitly a subclass of the Object class, which is the root of the class hierarchy. This means that every class inherits methods from Object, such as toString(), hashCode(), and equals().


Summary

By the end of Day 9, readers will understand:

  1. What inheritance is and how it works in Java.

  2. How to implement different types of inheritance: single, multilevel, and hierarchical.

  3. The usage of the super keyword to access superclass constructors and methods.

  4. Method overriding and how it differs from overloading.

  5. How inheritance promotes code reuse and extensibility in object-oriented design.

This session on inheritance will equip readers with the knowledge to build more modular, reusable, and maintainable Java applications. Understanding inheritance is crucial for mastering object-oriented programming, and this topic lays the foundation for more advanced OOP concepts. So Stay tuned!!.