Inheritance is a feature of object-oriented programming that allows you to define a new class based on an existing class, enabling code reuse and promoting a hierarchical relationship among classes.
The class that extends another class is called Child class or Sub class and the class being extended is call Parent class or Super class.
When a class extends another class, it gets access to all the properties and methods of the parent class, provided they do not have private access.
In java, inheritance is considered as an IS-A relationship, since child object is of same type as its parent.
Inheritance Syntax
Inheritance in java is achieved using extends
keyword.
A class can become a child class of another class by writing extends
followed by the parent class name as shown below
class Child extends Parent { }
Remember that the parent class must be visible to the child class, meaning that it should not be private
Also, if the parent class has default(package level) access and the child class should be in the same package.
When a class inherits another class, its object can access all its methods and variables using dot operator, similar to how it accesses its own properties.
Calling Parent class method
To call a method of parent class or access its properties from child class, super
keyword is used.
Simply write super
followed by dot and the name of method or property inside child class.
Calling Parent class constructor
Though a parent class constructor is implicitly called from child class constructor.
But, you can also call it explicitly using super
followed by parenthesis and appropriate arguments.
Note that super()
MUST be the first line in child class constructor.
Inheritance in Java Example
Below is an example of inheritance in java, where a parent class MobilePhone
is extended by SmartPhone
// Parent class class MobilePhone { private String brand; private String model; private String screenSize; // Constructor public MobilePhone(String brand, String model, String size) { this.brand = brand; this.model = model; this.screenSize = size; } // Method to get mobile phone details public void getDetails() { System.out.println("Brand: " + brand); System.out.println("Model: " + model); System.out.println("Screen Size: " + screenSize); } } // Child class inheriting from MobilePhone class Smartphone extends MobilePhone { private String operatingSystem; // Constructor public Smartphone(String brand, String model, String size, String os) { // Call parent class constructor using super keyword super(brand, model, size); this.operatingSystem = os; } // Method to get smartphone details public void getSmartphoneDetails() { // Call parent class method using super keyword super.getDetails(); System.out.println("Operating System: " + operatingSystem); } } public class Main { public static void main(String[] args) { // Create an instance of Smartphone class Smartphone myPhone = new Smartphone("Samsung", "Galaxy S21", "6.2 inches", "Android"); // Call child class method myPhone.getSmartphoneDetails(); } }
Below is the output
Brand: Samsung
Model: Galaxy 21
Screen Size: 6.2 inches
Operating System: Android
- In this example,
MobilePhone
is the parent class with fieldsbrand
,model
, andscreenSize
, and a methodgetDetails()
to print the mobile phone details. Smartphone
is the child class that inherits fromMobilePhone
and adds its own fieldoperatingSystem
.- The constructor of
Smartphone
class initializes theoperatingSystem
field and calls the constructor of the parent class (MobilePhone
) using thesuper
keyword. - The
getSmartphoneDetails()
method in theSmartphone
class calls thegetDetails()
method from the parent class using thesuper
keyword and then prints theoperatingSystem
field specific to theSmartphone
class. - In the
main
method, we create an instance of theSmartphone
class and call its method, which in turn calls parent class method usingsuper
keyword.
Benefits of Inheritance in Java
Following are the benefits of inheritance in java:
1. Code Reusability
Child classes share methods and fields of their parent class.
This means that the same code is reusable across multiple places.
2. Ease of Maintenance
Since code is shared, a change performed in super class is reflected for all child classes and it does not needs to be done for each child individually, making maintenance easier.
3. Abstraction Support
Inheritance supports the concept of abstraction, where common characteristics and behaviors are abstracted into a superclass, while specific details are implemented in subclasses.
This allows for a higher level of abstraction and encapsulation, leading to cleaner and more maintainable code.
4. Polymorphism
Inheritance enables polymorphic behavior, where objects of different subclasses can be assigned to a super class reference.
This allows for more flexible and extensible code, as new subclasses can be added without modifying existing code that uses the superclass interface(reference).
Method Overriding in Child Classes
A child class gets access to parent class methods implicitly. But, there are situations when child class needs its own specific implementation.
For example,
Consider a parent class Account
with a method withdraw()
that deducts a specified amount from the account balance.
In the parent class, the withdraw()
method may have a default implementation that performs the deduction based on certain rules, such as checking for available balance and deducting the amount accordingly.
Now, let’s say there are different types of accounts, such as SavingsAccount
and CheckingAccount
, which are subclasses of Account
.
Each type of account may have its own rules and restrictions for withdrawals.
For example, a SavingsAccount
may have a limit on the number of withdrawals allowed per month, while a CheckingAccount
may not have such restrictions.
In such scenarios, child classes can implement a method of parent class in their own specific way, which is also called Method Overriding in java.
So, the child classes (SavingsAccount
and CheckingAccount
) would need to override the withdraw()
method to implement their specific withdrawal rules.
The SavingsAccount
class may override the withdraw()
method to check if the withdrawal exceeds the monthly limit, while the CheckingAccount
class may simply deduct the amount without any additional checks.
Types of Inheritance in Java
In Java, there are different types of inheritance that can be implemented, each serving a specific purpose.
It is crucial to understand these variations to effectively leverage the power of inheritance in object-oriented programming.
Let’s explore into the various types of inheritance in Java:
1. Single Inheritance
In single inheritance, a class inherits from only one superclass. This means that a subclass can have only one direct parent class. Example,
public class Parent { // Parent class code here } public class Child extends Parent { // Child class code here }
By utilizing single inheritance, classes can achieve a clear and structured hierarchy, enhancing code readability and maintainability.
2. Multilevel Inheritance
For multilevel inheritance, a subclass is derived from another subclass, creating a hierarchical structure.
That is, a child class has a parent, which is the child of another parent and so on. Example,
public class Grandparent { // Grandparent class code here } public class Parent extends Grandparent { // Parent class code here } public class Child extends Parent { // Child class code here }
This type of inheritance allows for the extension of classes through multiple levels, enabling greater flexibility in code design and implementation.
To achieve multilevel inheritance in Java, classes are structured in a cascading manner, with each subsequent subclass inheriting properties and behaviors from its immediate parent class.
This cascading effect allows for the creation of complex class hierarchies, enhancing code reusability and modularity.
3. Hierarchial Inheritance
Hierarchial inheritance is when two or more classes extend the same class.
Simplest real life example is real brothers and sisters. They have same father or parent class.
Example,
class Television { void display(){ } } class Led extends Television { void display() { } } class Plasma extends Television { void display() { } }
4. Multiple Inheritance
Multiple inheritance is when a class extends more than one class or has more than one parents.
This type of inheritance is not supported in java using classes and we will understand the reason in coming sections.
5. Hybrid Inheritance
Hybrid inheritance is a combination of multiple types of inheritance within a single class hierarchy.
It typically involves the use of both single inheritance (where a class inherits from only one superclass) and multiple inheritance (where a class inherits from more than one superclass) in the same hierarchy.
In a hybrid inheritance scenario, classes can inherit properties and behaviors from multiple super classes, leading to complex class relationships.
This can introduce challenges such as ambiguity in method resolution and the diamond problem (where the same method is inherited from multiple super classes).
Why Multiple Inheritance is not supported
Multiple inheritance is not supported in Java primarily to avoid the complexity and ambiguity that can arise from it.
There are several reasons why Java does not allow multiple inheritance:
1. Diamond Problem
If a class inherits from two or more classes that have a common superclass. This can result in ambiguity when resolving method calls or accessing shared members, as the compiler may not know which superclass implementation to use.
This is called Diamond Problem.
2. Complexity
Multiple inheritance introduces additional complexity to the language and runtime environment, as it requires more sophisticated mechanisms for method resolution, memory layout, and object initialization.
3. Namespace Pollution
Multiple inheritance can lead to namespace pollution, where subclasses inherit conflicting or redundant members from multiple super classes.
This can make the codebase harder to understand and maintain, as it may introduce unnecessary complexity and dependencies.
Multiple Inheritance Using Interface
Multiple Inheritance is when a class extends more than one classes. This is NOT allowed in java using classes.
But, you can achieve multiple inheritance using interfaces. That is, a class is allowed to implement more than one interfaces.
This way it can implement methods of two different interfaces.
A class can implement more than one interfaces separated by a comma.
Example of multiple inheritance in java using interfaces is given below
interface A { void methodA(); } interface B { void methodB(); } public class Multiple implements A, B { void methodA() { System.out.println("Interface A"); } void methodB() { System.out.println("Interface B"); } }
Remember that if the interfaces implemented by a class have a default method with same name, then it will be a compiler error.
Duplicate default methods named go() with parameters are inherited from types B and A
where go()
is a default method defined in both interfaces.
Inheritance vs Composition
Composition is a design principle in which a class contains one or more instances of other classes (objects) as member variables.
Rather than inheriting behavior, a class delegates responsibilities to its component objects. Example,
public interface Engine { void start(); } public class Vehicle { private Engine engine; public void startEngine() { engine.start(); } }
In this example, Vehicle
class is contains reference to an Engine
object, which is responsible for implementation of start()
method.
Below are some important differences between Inheritance and Composition in java
1. Relationship
Inheritance establishes an “is-a” relationship between classes, while composition establishes a “has-a” relationship.
2. Flexibility
Composition is more flexible than inheritance because it allows classes to change behavior dynamically by swapping out components.
Inheritance, on the other hand, creates a tight coupling between subclasses and super classes, making it less flexible.
3. Code Reuse
Inheritance promotes code reuse by inheriting properties and behaviors from a superclass.
Composition promotes code reuse by reusing components in multiple classes.
4. Complexity
Inheritance can lead to deep class hierarchies, making the codebase complex and harder to maintain.
Composition, when used appropriately, can simplify the codebase by breaking it down into smaller, more manageable components.
5. Overriding vs Delegation
Inheritance allows subclasses to override superclass methods to customize behavior.
Composition delegates responsibilities to component objects, which can be swapped out or modified independently.
Conclusion
In conclusion, inheritance in Java is a powerful mechanism that allows for code reuse, flexibility, and abstraction.
From single to hierarchical and interface-based inheritance, Java provides various ways to structure and organize code effectively.
While multiple inheritance is not supported due to complexity and ambiguity concerns, interfaces offer a versatile alternative for achieving similar functionality.
By understanding and leveraging inheritance effectively, Java developers can create more modular, maintainable, and extensible software solutions.