Important Concepts of Object-Oriented system (Part III)
4. Hierarchy (Inheritance)
Introduction
This is an important pillar of OOPs. It is the mechanism by which one class is allowed to inherit the features (data members and methods) of another class. In Java, if we want to inherit any class to another class we have to use extends keyword. Inheritance always symbolizes IS-A relationship.
EX:-
//Employee.javapackage com.thirstybrain.app;public abstract class Employee {private int id;
private String name;public Employee(int id,String name){
this.id=id;
this.name=name;
System.out.
println("Invoked form abstract class Employee contructor ");
}public int getId() {
return id;
}public void setId(int id) {
this.id = id;
}public String getName() {
return name;
}public void setName(String name) {
this.name = name;
}public String getEmployeeDetail(){
System.out.
println(“Invoked from Employee class getEmployeeDetail method”)
return "Id : "+id+" Name : "+name;
}public abstract double getSalaryDetail();
}//FulltimeEmployee.javapackage com.thirstybrain.app;import com.thirstybrain.app.Employee;public class FulltimeEmployee extends Employee{
private double salary;
public FulltimeEmployee(int id, String name,double salary)
{
super(id, name);
this.salary=salary;
System.out.
println("Invoked form class Employee contructor ");
}public double getSalary() {
return salary;
}public void setSalary(double salary) {
this.salary = salary;
}
public String getEmployeeDetail(){
System.out.println("Invoked from FulltimeEmployee class ,getEmployeeDetail() method");
return "";
}@Override
public double getSalaryDetail() {
return salary;
}}//Program.Javapackage com.thirstybrain.app;import com.thirstybrain.app.FulltimeEmployee;public class Program {public static void main (String [] args) {//1. Constructor calling sequence
Employee employeeObjC=new FulltimeEmployee(1, "shivam",10000.00);//Output
//Invoked form abstract class Employee contructor
//Invoked form class Employee contructor
//Reason: Since, we are doing constructor chaining thats why
//base class constructor is first get called
//and then child class constructor gets called.FulltimeEmployee fulltimeEmployeeObjC=
new FulltimeEmployee(2, "Raj", 100000.00);//Output
//Invoked form abstract class Employee contructor
//Invoked form class Employee contructor
//Reason: Since, we are doing constructor chaining thats why
//base class constructor is first get called
//and then child class constructor gets called.Employee employeeObj = new FulltimeEmployee(1, "shivam",10000.00);
employeeObj.getEmployeeDetail();//Output: -
//Invoked form abstract class Employee contructor
//Invoked form class Employee contructor
//Invoked from FulltimeEmployee class, getEmployeeDetail() method
//Reason: Since we are using object of FulltimeEmployee classs //i.e.child class.That's why getEmployeeDetail of
//FulltimeEmployee class child class get called.FulltimeEmployee fulltimeEmployeeObj =
new FulltimeEmployee(1, "shivam",10000.00);
fulltimeEmployeeObj.getEmployeeDetail();//Output: -
// Invoked form abstract class Employee contructor
//Invoked form class Employee contructor
//Invoked from FulltimeEmployee class, getEmployeeDetail() method
// Reason: Since we are using object of FulltimeEmployee classs //i.e.child class
//That's why getEmployeeDetail of FulltimeEmployee class
// i.e child class get called.}}
Why we use inheritance?
· For method overriding
· Code reusability.
Types of inheritance in Java and .NET


· Single Inheritance: -
EX:-
//Employee.java
package com.thirstybrain.app.single;public class Employee {
public int id;
public String name;public void getEmployeeDetail(){
System.out.println("Invoked getDetail from Employee Class ");
}
}//FulltimeEmployee.java
package com.thirstybrain.app.single;public class FulltimeEmployee extends Employee {
public void getFulltimeEmployeeDetail(){
System.out.
println("Invoked getFulltimeEmployeeDetail from FulltimeEmployee Class ");}}//Program.java
package com.thirstybrain.app.single;public class Program {
public static void main(String[] args) {
FulltimeEmployee fulltimeEmployeeObj=new FulltimeEmployee();
fulltimeEmployeeObj.getEmployeeDetail();
//Output : Invoked getDetail from Employee ClassfulltimeEmployeeObj.getFulltimeEmployeeDetail();
//Output :
//Invoked getFulltimeEmployeeDetail from FulltimeEmployee Class
}
}
· Multi-Level Inheritance : -
EX:-
//Employee.java
package com.thirstybrain.app.multilevel;public class Employee {
public int id;
public String name;
public void getEmployeeDetail(){
System.out.println("Invoked getDetail from Employee Class ");
}
}//FulltimeEmployee.java
package com.thirstybrain.app.multilevel;import com.thirstybrain.app.multilevel.Employee;public class FulltimeEmployee extends Employee {
public void getFulltimeEmployeeDetail(){
System.out.println("Invoked getFulltimeEmployeeDetail from FulltimeEmployee Class ");
}
}//Manager.java
package com.thirstybrain.app.multilevel;public class Manager extends FulltimeEmployee {
public void getManagerDetail(){
System.out.println("Invoked getManagerDetail from Manager Class ");
}
}//Program.java
package com.thirstybrain.app.multilevel;public class Program {
public static void main(String[] args ){
Manager managerObj=new Manager();
managerObj.getEmployeeDetail();
//Output : Invoked getDetail from Employee ClassmanagerObj.getFulltimeEmployeeDetail();
//Output :
//Invoked getFulltimeEmployeeDetail from FulltimeEmployee ClassmanagerObj.getManagerDetail();
//Output : Invoked getManagerDetail from Manager Class}}
· Hierarchical Inheritance : -
EX:-
//Employee.javapackage com.thirstybrain.app.hierarchical;public class Employee {public void getEmployeeDetail(){
System.out.println("Invoked getEmployeeDetail from Employee class");
}}//FulltimeEmployee.java
package com.thirstybrain.app.hierarchical;public class FulltimeEmployee extends Employee {public void getFulltimeEmployeeDetail(){
System.out.println("Invoked getFulltimeEmployeeDetail from FulltimeEmployee class");}}//ContractEmployee.java
package com.thirstybrain.app.hierarchical;public class ContractEmployee extends Employee {
public void getContractEmployeeDetail(){
System.out.
println("Invoked getContractEmployeeDetail from ContractEmployee class");
}}//Program.Java
package com.thirstybrain.app.hierarchical;public class Program {
public static void main( String [] args){
ContractEmployee contractEmployee =new ContractEmployee();
contractEmployee.getContractEmployeeDetail();
//Output:
//Invoked getContractEmployeeDetail from ContractEmployee classcontractEmployee.getEmployeeDetail();
//Output: Invoked getEmployeeDetail from Employee class}}
· Multiple Inheritance: -
EX:-
//Manager.java
package com.thirstybrain.app.multiple;public class Manager {
public void getDeveloperDetail(){
System.out.println("Invoked getManagerDetail from Manager Class ");
}}//Developer.java
package com.thirstybrain.app.multiple;public class Developer {
public void getDeveloperDetail(){
System.out.println("Invoked getDeveloperDetail from Developer Class ");
}
}//Employee.java
package com.thirstybrain.app.multiple;public class Employee extends Manager,Developer{//it will give error at compile time because java doesn't supports
//Multiple inheritancepublic void getDeveloperDetail(){
System.out.
println("Invoked getDeveloperDetail from Developer Class ");
}}
Why Java doesn’t support multiple Inheritance?
Let’s consider above scenario, getDeveloperDetail() method is in all the three classes (i.e. Manager, Developer, Employee ).if we write below lines of code whose getDeveloperDetail() method would be invoked. There would be ambiguity to call a method of Developer or Manager class. That’s why compiler will throw an error at compile time.
Employee employee =new Employee();
employee.getDeveloperDetail();
Solution:-
If we want to use a method from both the classes, we can achieve it: -
· By implementing interfaces
//Reports.java
package com.thirstybrain.app.multiple;public interface Reports {
public static final String companyName="thirstyBrain";
void getReport();
}//PowerBIReport.java
package com.thirstybrain.app.multiple;public class PowerBIReport implements Reports { @Override
public void getReport() {
System.out.
println("Invoked getReport from PowerBIReport Class ");
}
}//D3Report.java
package com.thirstybrain.app.multiple;public class D3Report{ public void getReport(){
System.out.println("Invoked getReport from D3Report Class ");
}
}//Program.java
package com.thirstybrain.app.multiple;public class Program extends D3Report implements Reports {
public static void main(String[] args) {
////case 1
Reports report = new PowerBIReport();
report.getReport();
////Output : Invoked getReport from PowerBIReport Class
System.out.
println("Company Name is : "+ Reports.companyName);
////Output : Company Name is : thirstyBrain
//Case 2
D3Report d3ReportObj=new D3Report();
d3ReportObj.getReport();
////Output : Invoked getReport from D3Report Class }
}
A few developers will be surprised when they will see below code in Report Interface.
public static final String companyName="thirstyBrain";
Can we specify the member variables in an interface?
yes, we can specify the member variables in an interface.
why interface member variables or fields are public, static and final by default?
Interface can’t be instantiated in their own.
public access modifier provides flexibility to the member variable through which they can be easily accessed by anyone who is implementing the interface.
Static because the value of the variable must be assigned in a static context in which no instance exists.
The final modifier ensures the value assigned to the interface variable is a true constant that cannot be re-assigned by program code.
· Hybrid Inheritance:-
Ex:
public class Person{
public void getPersonDetail(){
System.out.println("getPersonDetail() method of Person");
}
}public class Developer extends Person{
public void show(){
System.out.println("show() method of Developer");
}
public void getDeveloperDetail(){
System.out
.println("getDeveloperDetail() method of Developer");
}
}public class Manager extends Person{ public void show(){
System.out.println("show() method of Manager");
} public void getManagerDetail(){
System.out.println("getManagerDetail() method of Manager");
}
}public class Employee extends Developer,Manager{ public void getEmployeeDetail(){
System.out.println("getEmployeeDetail() method of Employee");
}
public static void main(String args[]){
Employee employeeObj = new Employee();
employeeObj.getEmployeeDetail();
employeeObj.show();
//Confusion happens here which show method to call
}
}//Output : This code will give us compile-time error because of the ambiguity problem
Hybrid Inheritance is a mix of two or more above type of inheritances. This problem will also have solved by implementing interfaces.
Can we inherit constructor of Super class?
A Child Class inherits all the members (i.e. field, methods and nested classes) from its Parent class. Constructors are not members, so they are not inherited by Child classes. But, the constructor of the Parent class can be invoked from the Child class.
Can Child class be able to access private members of Parent class?
No, Child class can be able to access public or protected members of the parent class.
[NOTE: If we will not implement inheritance properly then sometime it may introduce some problems. The famous two problems as mentioned below: -
· Fragile base class problem
· Sometimes inheritance violates encapsulation
]
Conclusion
Pros
- All the child class instances contain all the non-static, public or protected data member of the parent class.
- we can be able to override the method of parent class in the child class.
- Reusability — Public method or data member can be used in the child class.
Cons
- It introduces tight coupling among the inherited classes. Any change in the base class can impact the child classes.
- Sometimes a lot of data remains unused in the hierarchy. So memory wastage can happen in case of inheritance.