Introduction to Java | Inheritance
What is Inheritance in Java?
Inheritance is a mechanism in object-oriented programming (OOP) that allows one class (called the subclass or child class) to inherit the properties and methods of another class (called the superclass or parent class). This allows for code reuse, improves maintainability, and supports a hierarchical class structure.
In Java, inheritance is implemented using the extends
keyword, and it helps in establishing relationships between classes. The child class can:
- Access the non-private members (fields and methods) of the parent class.
- Override methods to provide a specific implementation.
- Add new fields and methods.
Advantages of Inheritance
- Code Reusability: Inheritance allows the reuse of code, which helps to avoid redundancy. The subclass can inherit properties and behaviors from the superclass.
- Method Overriding: A subclass can override the methods of the superclass to provide a specific implementation, which is useful for runtime polymorphism.
- Extensibility: New functionality can be added to existing classes without modifying their code, making it easier to extend the program in the future.
- Reduced Complexity: By using inheritance, we can organize code hierarchically and avoid redundancy, making it easier to manage and understand.
Types of Inheritance in Java
Java supports several types of inheritance, allowing you to design classes in different ways. These include:
- Single Inheritance: A class inherits from a single parent class.
- Multi-Level Inheritance: A class inherits from a subclass of another class.
- Hierarchical Inheritance: Multiple classes inherit from a single parent class.
- Multiple Inheritance (via interfaces): A class implements multiple interfaces, allowing it to inherit behavior from multiple sources.
1. Single Inheritance
Single inheritance is the simplest form of inheritance where a class can inherit from one superclass only. This means that the subclass inherits fields and methods from just one parent class.
Example: Below is a simple example where class Dog
inherits from class Animal
:
Code Example
class Animal {
void eat() {
System.out.println("This animal eats food.");
}
}
class Dog extends Animal {
void bark() {
System.out.println("Dog is barking.");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.eat(); // Inherited from Animal class
dog.bark(); // Specific to Dog class
}
}
2. Multi-Level Inheritance
Multi-level inheritance occurs when a class inherits from a subclass of another class. This creates a chain of inheritance where each subclass inherits from its immediate parent, which is itself a subclass of another class.
Example: In this example, class Grandchild
inherits from class Child
, and class Child
inherits from class Parent
.
Code Example
class Parent {
void display() {
System.out.println("This is the Parent class.");
}
}
class Child extends Parent {
void show() {
System.out.println("This is the Child class.");
}
}
class Grandchild extends Child {
void greet() {
System.out.println("This is the Grandchild class.");
}
}
public class Main {
public static void main(String[] args) {
Grandchild grandchild = new Grandchild();
grandchild.display(); // Inherited from Parent class
grandchild.show(); // Inherited from Child class
grandchild.greet(); // Specific to Grandchild class
}
}
3. Hierarchical Inheritance
In hierarchical inheritance, multiple subclasses inherit from a single superclass. This allows different classes to share common functionality defined in the parent class, reducing redundancy.
Example: In this example, class Dog
and class Cat
both inherit from class Animal
, demonstrating how hierarchical inheritance works.
Code Example
class Animal {
void eat() {
System.out.println("This animal eats food.");
}
}
class Dog extends Animal {
void bark() {
System.out.println("Dog is barking.");
}
}
class Cat extends Animal {
void meow() {
System.out.println("Cat is meowing.");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.eat(); // Inherited from Animal class
dog.bark(); // Specific to Dog class
Cat cat = new Cat();
cat.eat(); // Inherited from Animal class
cat.meow(); // Specific to Cat class
}
}
4. Multiple Inheritance (via Interfaces)
Java does not support multiple inheritance through classes, as it could lead to the "diamond problem" (ambiguity in method resolution). However, Java achieves multiple inheritance through interfaces. A class can implement multiple interfaces, allowing it to inherit methods from multiple sources.
Example: In the following example, class Dog
implements two interfaces, Animal
and Pet
, to achieve multiple inheritance.
Code Example
interface Animal {
void makeSound();
}
interface Pet {
void play();
}
class Dog implements Animal, Pet {
public void makeSound() {
System.out.println("Bark");
}
public void play() {
System.out.println("Dog is playing.");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.makeSound(); // Output: Bark
dog.play(); // Output: Dog is playing.
}
}
Method Overriding
Method overriding is a feature in Java that allows a subclass to provide a specific implementation of a method that is already defined in its superclass. The method in the subclass should have the same signature (name, parameters, and return type) as the one in the superclass.
Overriding is important for implementing runtime polymorphism, where the JVM dynamically determines which method to call based on the actual object type at runtime, not the reference type.
Code Example
class Animal {
void makeSound() {
System.out.println("Some generic animal sound");
}
}
class Dog extends Animal {
@Override
void makeSound() {
System.out.println("Bark");
}
}
public class Main {
public static void main(String[] args) {
Animal myDog = new Dog();
myDog.makeSound(); // Output: Bark (overridden method)
}
}
5. Abstract Classes and Inheritance
Abstract classes provide a way to declare classes that cannot be instantiated on their own but can serve as a superclass for other classes. An abstract class can contain abstract methods, which are methods that do not have a body and must be implemented by any subclass. This allows you to create a template for other classes to follow, enforcing a structure while providing some shared functionality.
Abstract classes are particularly useful when you want to define a base class that provides common functionality, but you also want to allow subclasses to implement certain methods according to their specific needs.
Code Example
abstract class Animal {
abstract void makeSound();
}
class Dog extends Animal {
void makeSound() {
System.out.println("Bark");
}
}
public class Main {
public static void main(String[] args) {
Animal dog = new Dog();
dog.makeSound(); // Output: Bark
}
}