Inheritance in JAVA.
Inheritance in JAVA.
In Java, inheritance serves as a fundamental mechanism where one object inherits all the characteristics and functionalities of a parent object. It plays a pivotal role in the Object-Oriented Programming paradigm.
The concept underlying inheritance in Java revolves around the ability to construct new classes based on pre-existing ones. By inheriting from an existing class, you gain access to the methods and attributes of the parent class, allowing for their reuse. Additionally, you have the liberty to introduce new methods and attributes within your current class.
Inheritance, in essence, embodies the IS-A relationship, often referred to as a parent-child relationship.
Why Do We Need Java Inheritance
Code Reusability: Inheritance allows child classes to directly utilize code from a common superclass. This promotes the reuse of code written in the superclass across multiple subclasses.
Method Overriding: Inheritance is the mechanism through which Java achieves method overriding. This enables the customization of methods in subclasses, leading to runtime polymorphism, where the appropriate method is chosen at runtime based on the object's actual type.
Abstraction: Inheritance facilitates the concept of abstraction, where not all implementation details need to be provided to the user. Abstraction presents the functionality of a class while hiding unnecessary complexities, enhancing the user's understanding of how to interact with the class.
Terms Used in Inheritance
Class: A class in Java serves as a blueprint or template for creating objects. It defines common characteristics and properties shared by objects of that class.
Superclass/Parent Class: The superclass, also known as the parent class or base class, is the class whose features (fields and methods) are inherited by other classes.
Subclass/Child Class: A subclass, also referred to as a derived class, extended class, or child class, is a class that inherits the attributes and behaviors of another class (the superclass). Subclasses can also introduce their own fields and methods in addition to those inherited.
Reusability: Inheritance facilitates code reusability. When you need to create a new class and find that an existing class already contains some of the code you require, you can derive the new class from the existing one. This allows you to reuse the fields and methods from the existing class, promoting efficient and modular code development
syntax of Java Inheritance:-
class Subclass extends Superclass {
// fields and methods
}
Java Inheritance Example:-
class Employee {
int salary = 45000;
}
class HR extends Employee {
int bonus = 20000;
public static void main(String args[]) {
HR h = new HR();
System.out.println("HR salary is: " + h.salary);
System.out.println("Bonus of HR is: " + h.bonus);
}
}
Output:-
HR salary is: 45000
Bonus of HR is: 20000
The main types of inheritance in Java are:
Single Inheritance
Multilevel Inheritance
Hierarchical Inheritance
Multiple Inheritance
Hybrid Inheritance
Single Inheritance
Single inheritance refers to a class inheriting from only one superclass (parent class).
Java supports single inheritance for classes.
class A {
// ...
}
class B extends A {
// ...
}
Example
class Animal {
void eat() {
System.out.println("Animal is eating.");
}
}
class Dog extends Animal {
void bark() {
System.out.println("Dog is barking.");
}
}
public class Main {
public static void main(String[] args) {
Dog myDog = new Dog();
myDog.eat(); // Inherited from Animal class
myDog.bark(); // Defined in Dog class
}
}
Output:-
Animal is eating.
Dog is barking.
In this example, the Dog class inherits from the Animal class using single inheritance. It can access and use the eat method inherited from the Animal class while also having its own method bark
2.Multilevel Inheritance
In multilevel inheritance, a subclass inherits from a base class, and this subclass can also act as a base class for other classes. In the provided image, class A is the base class for derived class B, and B in turn serves as the base class for derived class C. In Java, a class is unable to directly access the members of its grandparent class.
class Grandparent {
// ...
}
class Parent extends Grandparent {
// ...
}
class Child extends Parent {
// ...
}
example Java program that illustrates multilevel inheritance:
class Grandparent { \
void displayGrandparent() {
System.out.println("This is the Grandparent class.");
}
}
class Parent extends Grandparent {
void displayParent() {
System.out.println("This is the Parent class.");
}
}
class Child extends Parent {
void displayChild() {
System.out.println("This is the Child class.");
}
}
public class MultilevelInheritanceExample {
public static void main(String[] args) {
Child child = new Child();
// Calling methods from each class in the inheritance chain
child.displayGrandparent(); // Method from Grandparent class
child.displayParent(); // Method from Parent class
child.displayChild(); // Method from Child class
}
}
In this example:
Grandparent is the top-level class in the inheritance hierarchy.
Parent inherits from Grandparent, and Child inherits from Parent.
The MultilevelInheritanceExample class demonstrates the usage of these classes.
When you create an instance of the Child class, you can access methods from all three classes in the chain: Grandparent, Parent, and Child.
When you run the program, it will produce the following output:
This is the Grandparent class.
This is the Parent class.
This is the Child class.
2.Hierarchical Inheritance
Hierarchical Inheritance in Java involves a scenario where a single class, often referred to as the superclass or base class, serves as the parent for multiple subclasses. In the context of the image provided, class A plays the role of the base class, and it serves as the common ancestor for the derived classes B, C, and D.
Syntax:-
class Animal {
// ...
}
class Dog extends Animal {
// ...
}
class Cat extends Animal {
// ...
}
example Java program that illustrates Hierarchical inheritance:
class Animal {
void eat() {
System.out.println("The animal is eating.");
}
}
class Dog extends Animal {
void bark() {
System.out.println("The dog is barking.");
}
}
class Cat extends Animal {
void meow() {
System.out.println("The cat is meowing.");
}
}
class Lion extends Animal {
void roar() {
System.out.println("The lion is roaring.");
}
}
public class HierarchicalInheritanceExample {
public static void main(String[] args) {
Dog dog = new Dog();
Cat cat = new Cat();
Lion lion = new Lion();
// Invoke methods from each subclass
dog.eat(); // Method from Animal class
dog.bark(); // Method from Dog class
cat.eat(); // Method from Animal class
cat.meow(); // Method from Cat class
lion.eat(); // Method from Animal class
lion.roar(); // Method from Lion class
}
}
In this example:
Animal is the superclass, and it contains a method eat() that is inherited by its subclasses.
Dog, Cat, and Lion are the subclasses that extend the Animal class. Each of them has their own unique methods (bark(), meow(), and roar()).
The HierarchicalInheritanceExample class demonstrates the usage of these classes.
When you create instances of each subclass and invoke methods, you can see that they inherit the eat() method from the Animal class and have their own specialized methods.
When you run the program, it will produce the following output:
The animal is eating.
The dog is barking.
The animal is eating.
The cat is meowing.
The animal is eating.
The lion is roaring.
This output confirms that each subclass inherits from the Animal superclass, creating a hierarchical inheritance structure.
4.Multiple inheritances
Multiple inheritance allows a class to inherit from more than one superclass. However, Java does not support multiple inheritance for classes (i.e., a class cannot directly inherit from multiple classes). Instead, Java uses interface inheritance to achieve a form of multiple inheritance. A class can implement multiple interfaces, effectively inheriting their method signatures.
Syntax:-
interface InterfaceA {
void methodA();
}
interface InterfaceB {
void methodB();
}
class MyClass implements InterfaceA, InterfaceB {
public void methodA() {
// ...
}
public void methodB() {
// ...
}
}
example Java program that illustrates Multiple inheritance:
// First interface
interface Flying {
void fly();
}
// Second interface
interface Swimming {
void swim();
}
// Concrete class implementing both interfaces
class Bird implements Flying, Swimming {
@Override
public void fly() {
System.out.println("The bird is flying.");
}
@Override
public void swim() {
System.out.println("The bird is swimming.");
}
}
public class MultipleInheritanceExample {
public static void main(String[] args) {
Bird bird = new Bird();
bird.fly(); // Call the fly() method from the Flying interface
bird.swim(); // Call the swim() method from the Swimming interface
}
}
In this example:
We have two interfaces, Flying and Swimming, each defining a method.
The Bird class implements both Flying and Swimming interfaces.
The MultipleInheritanceExample class demonstrates the usage of the Bird class.
When you run the program, it will produce the following output:
The bird is flying.
The bird is swimming.
In this way, you achieve a form of multiple inheritance in Java by having a class implement multiple interfaces. Each interface can define a set of methods, and a class that implements those interfaces must provide concrete implementations for all of the methods defined in those interfaces.
5.Hybrid Inheritance:
Hybrid inheritance is a combination of different types of inheritance within a single program. For example, you can have a class that uses single inheritance and interfaces (multiple inheritance) together.
Syntax:-
class Parent {
// ...
}
interface InterfaceA {
void methodA();
}
class Child extends Parent implements InterfaceA {
public void methodA() {
// ...
}
}
example Java program that illustrates hybrid inheritance:
// Step 1: Create an interface
interface Vehicle {
void start();
void stop();
}
// Step 2: Create a superclass
class Engine {
void ignite() {
System.out.println("Engine ignited.");
}
void shutDown() {
System.out.println("Engine shut down.");
}
}
// Step 3: Create a subclass that extends the superclass
class Car extends Engine implements Vehicle {
@Override
public void start() {
ignite();
System.out.println("Car started.");
}
@Override
public void stop() {
shutDown();
System.out.println("Car stopped.");
}
}
// Step 4: Create another subclass that implements the interface
class Bicycle implements Vehicle {
@Override
public void start() {
System.out.println("Bicycle started pedaling.");
}
@Override
public void stop() {
System.out.println("Bicycle stopped pedaling.");
}
}
public class HybridInheritanceExample {
public static void main(String[] args) {
// Create instances of the classes
Car car = new Car();
Bicycle bicycle = new Bicycle();
// Use the objects
System.out.println("Using the car:");
car.start();
car.stop();
System.out.println("\nUsing the bicycle:");
bicycle.start();
bicycle.stop();
}
}
In this example:
We create an interface called Vehicle with two methods, start() and stop(), to represent vehicle behaviors.
We create a superclass called Engine that contains methods related to engine ignition and shutdown.
We create a Car class that extends the Engine class and implements the Vehicle interface. This demonstrates single inheritance from Engine and interface inheritance from Vehicle.
We create a Bicycle class that implements the Vehicle interface.
In the main method, we create instances of both Car and Bicycle and demonstrate how they can exhibit different behaviors based on their inheritance.
When you run the program, it will produce the following output:
Using the car:
Engine ignited.
Car started.
Engine shut down.
Car stopped.
Using the bicycle:
Bicycle started pedaling.
Bicycle stopped pedaling.
This demonstrates hybrid inheritance by combining single inheritance (from Engine) and interface inheritance (from Vehicle).
Advantages Of Inheritance in Java:
1. **Code Reusability**: Inheritance allows you to reuse code from an existing class. Instead of writing similar code from scratch, you can extend an existing class and override or add new behavior as needed.
2. **Promotes Modularity**: Inheritance helps in breaking down complex systems into manageable, modular components. Each class can represent a specific entity or behavior, making the code easier to understand, maintain, and extend.
3. **Eliminates Redundancy**: Common attributes and methods can be defined in a superclass. Subclasses inherit these members, reducing the need to duplicate code across different classes.
4. **Extensibility**: You can create new subclasses to extend the functionality of existing classes. This allows for incremental development, where new features can be added without modifying the existing code.
5. **Polymorphism**: Inheritance is a key factor in achieving polymorphism. This allows objects of different types to be treated uniformly if they are part of the same inheritance hierarchy.
6. **Encapsulation**: Inheritance helps in grouping related behavior and data together. This contributes to better code organization and reduces the risk of exposing sensitive data or methods to unauthorized access.
7. **Flexibility and Adaptability**: Through inheritance, you can define generic classes and then create specialized subclasses to adapt and cater to specific requirements. This provides flexibility in designing solutions for different scenarios.
8. **Facilitates Method Overriding**: Subclasses can override methods from the superclass. This allows for customization of behavior without modifying the original class.
9. **Promotes Code Consistency**: Inheritance helps in maintaining a consistent style and structure across related classes. This makes it easier for multiple developers to collaborate on a project.
12. **Enhances Code Readability**: Inheritance relationships can make code more readable and intuitive. It provides a clear indication of the relationships and hierarchies between different classes.
Disadvantages of Inheritance in Java
1. **Tight Coupling**: Inheritance can lead to tight coupling between the superclass and its subclasses. Changes in the superclass can affect the behavior of all subclasses, potentially causing unintended consequences.
2. **Inflexibility**: Once a class is defined with a certain inheritance hierarchy, it can be challenging to change that hierarchy without affecting existing code. This lack of flexibility can lead to design limitations.
3. **Complexity**: Deep and complex inheritance hierarchies can become difficult to understand and maintain. It may become challenging to trace the origin of a particular method or attribute in deeply nested hierarchies.
4. **Fragile Base Class Problem**: When changes are made to a base class (superclass), they can inadvertently break functionality in derived classes (subclasses). This is known as the "fragile base class problem" and can lead to unexpected issues.
5. **Inefficient Memory Usage**: In some cases, inheritance can lead to inefficient memory usage. Subclasses inherit all the attributes and methods of their superclasses, even if they don't need all of them, which can result in wasteful memory consumption.
6. **Limited to Single Inheritance**: In Java, classes can inherit from only one superclass (single inheritance). This limitation can be a drawback when trying to model complex relationships or when a class needs to inherit behavior from multiple sources.
7. **Overhead**: Inheritance introduces some overhead, such as method lookup and dynamic dispatch, which can slightly impact performance. In cases where performance is critical, other mechanisms like composition may be preferred.
8. **Lack of Encapsulation**: Inheritance can expose subclass internals to the superclass, potentially violating encapsulation principles. Subclasses may need to expose fields or methods to the superclass, making them less private.
9. **Difficulty in Testing**: Inheritance can make it challenging to write isolated unit tests for subclasses. Testing can become complex when subclasses rely on the behavior of their superclasses.
10. **Diamond Problem (for Multiple Inheritance)**: While Java supports multiple inheritance through interfaces, it avoids the diamond problem by not allowing multiple inheritance of state (i.e., multiple inheritance of classes). This limitation can be a disadvantage in situations where multiple inheritance of state is necessary.
11. **Reduced Code Reusability**: Overuse of inheritance for code reuse can lead to rigid and less reusable code. Subclasses may become tightly coupled to their superclasses, making it difficult to reuse them in different contexts.
Default Superclass: In Java, every class, except for the Object class, inherits from one and only one direct superclass, adhering to the principle of single inheritance. If no explicit superclass is defined, the class is implicitly a subclass of the Object class.
Single Superclass: While a superclass can have multiple subclasses, a subclass can have only one superclass. Java does not support multiple inheritances with classes, although it does support multiple inheritances through interfaces.
Inheritance of Constructors: Subclasses inherit all members (fields, methods, and nested classes) from their superclasses. However, constructors are not considered members and, therefore, are not inherited. Nonetheless, the constructor of the superclass can be invoked from the subclass to initialize the inherited members.
Private Member Inheritance: Subclasses do not inherit the private members (fields or methods) of their parent class. Nevertheless, if the superclass provides public or protected methods (such as getters and setters) for accessing its private fields, these can also be utilized by the subclass.