Spread the love

Learn Inheritance In Java Fast with Examples

Spread the love

Inheritance In Java:

Inheritance provides us with the ability to make new, more versatile objects from already compiled objects without changing the original object. It also allows us to write new classes based on existing classes without changing the existing class in any way. Inheritance allows descendants of a class (known as child class or subclass) to inherit all of its member elements and methods from its ancestor(Known as Parent class or superclass).

The advantage of Inheritance is that it supports incremental development by allowing us to write new code without affecting the previously deployed code. By inheriting from an existing functional class, we add new methods and data members. This mechanism leaves the actual code as it is and all changes happen to be in defined in the derived class. This also helps in tracking the bugs easily.
Another aspect of Inheritance is that we don’t need the source code of the base class. Rather we need to import that class and write an extend keyword to our class.No copy-paste is required.
Inheritance works as a building block providing incremental support which is very much sustainable.

The inheritance allows subclasses to inherit all the variables and methods of their parent class.
The inheritance can be of many different forms:

  1. Single inheritance(only one superclass)
  2. Multiple inheritances (several superclasses)
  3. Hierarchical inheritance(One superclass and many subclasses)
  4. Multilevel inheritance(Derived from a derived class).

Single inheritance(only one superclass):

Here B will contain all the public methods and variables of A.
The inheritance path is A->B

Multiple inheritances (several superclasses):

Not directly supported by java but C will have all public variables and methods of A and B.
The inheritance path is A->C and B->C

Hierarchical inheritance(One superclass and many subclasses):


This is the most real and common scenario when designing a real-time application or issue.
The inheritance path is bird->duck
bird->cuckoo
bird->ostrich

Multilevel inheritance(Derived from a derived class).


Class B will have all the public variables and methods of A apart from its methods and variables and C will have all the public methods and variables of B. Technically C will have all methods and variables of A and B.
The inheritance path is A->B->C

An Example:

class MyClass{
    public int x,y;
    MyClass(int x,int y)
    {
        this.x=x;
        this.y=y;
    }
}
class MyAnotherClass extends MyClass{
    int z;
    //inherits x,y from 
    MyAnotherClass(int x,int y,int z)
    {
    //code duplication
    //this.x=x;
    //this.y=y;
    //instead use super
    super(x,y);         
    this.z=z;
    }
    void displayValues()
    {
        System.out.println(x+y+z);
    }
}
public class TestInheritance{
    public static void main(String args[])
    {
        MyAnotherClass mac=new MyAnotherClass(3,2,2);
        mac.displayValues();
    }
} 

relax!! the code won’t compile if we do not activate super() and activate the two commented lines. This is just to show how we can do a repetition of data if we do not take help from Inheritance. To avoid the repetition of code, java uses a special keyword called Super, this can be used to refer directly to the superclass constructor.
this is another keyword used to tell java compiler that this will refer to the current object. Let us see one more example

class Toy{
    void createNoice()
    {
        System.out.println("DUM DUM");
    }
}
class RailToy extends Toy{
    void createNoice()
    {
        System.out.println("JHIK JHIK");
    } 
}
class BusToy extends Toy{
    static boolean noHorn;
    void createNoice()
    { 
        if(noHorn)
        super.createNoice();
        else
        System.out.println("GOOO");
    }
}
public class MyToy{
    public static void main(String args[])
    {
        RailToy rt=new RailToy();
        BusToy bt=new BusToy();
        bt.noHorn=true;
        bt.createNoice();
        rt.createNoice();
        bt.noHorn=false;
        bt.createNoice();
    }
}

The output of the code:
$javac MyToy.java
$java -Xmx128M -Xms16M MyToy
DUM DUM
JHIK JHIK
GOOO
Here createNoice() method is overridden in the respective classes, with a condition that if noHorn is set to true it will invoke the Toy class’s createNoice() method.

READ  Different Streams in Java
READ  What is the defference between driver.navigate().refresh() and pressing F5?

What Is HAS-A Relationship In Java??

Inheritance -HAS-A relationship
Inheritance -HAS-A relationship

When designing our classes, our basic tendency is to design classes maximum code reusability.  Reusable code means less work and maximum output. in this post, I have shown what are the prohibited concept of java in terms of extension. Now think about a scenario, I have a Tree class, I have to leave class and I have Root class as well.

‘is an’ relation or ‘ is a’ relationship refers to inheritance. It is an aggregation.

‘Has a’ relationship refers to composition.

Now Tree class has methods like-

  • Consume_water();
  • Takes_CO2()
  • Release_O2()
  • Provide_shelter()

Again for Leaves class, we can have the methods

  • Consume_water();
  • Takes_CO2()
  • Release_O2()

for Root class, we can have the methods…

  • Consume_water();
  • Provide_strength()

Now if you observe the methods of the classes(Tree, Leaves and Root) we can clearly say that Tree can be superclass and Leave and Root can be a subclass. By this approach, we can get more reusable code.
so the structure could be for Tree class.

class Tree{
public void Consume_water()
{
//consumes some water
}
Public void Takes_CO2()
{
//takes x amount of CO2
}
public int Release_O2()
{
//return some o2
}
}

For Leave class

class Leave extends Tree
{
//no methods are required as all will come from Tree
}

Similarly for Root class

class Root extends Tree
{
//no methods are required as all will come from Tree
public void Provide_Strength()
{
//provide some strength to tree
}
}

Looks like we are good to go!!!

But is it ok?? Surely no. The purpose of Tree is different from Leaves so as the corresponding methods. And to make a parent-child relationship the child has to follow the IS-A relationship.

Leaves IS(ARE)-A Tree?
or
Root IS-A Tree?

Both the answers are false. So this is not a valid parent-child relationship. Now the next question is “if we can not extend Root or leaves to Tree, then how to reuse those codes?? if not possible the code redundancy will be higher. Isn’t it?

To resolve such problem Java has come up with a concept called HAS-A Relationship.
Let us check the feature of HAS-A relationship

  • HAS-A relationship is also known as Composition or Aggregation
  • For IS-A relationship there is a keyword available called “extends” but for HAS-A relationship there is no such keyword available, Mostly we use new.
  • Code reusability is the core concept for HAS-A relationship
Class Tree{
Leaves lvs=new Leaves();
//It means Tree has leaves reference
Root rt=new Root();
//It means Tree has Roots reference

Even though HAS-A relationship resolves problems of extension. At the same time, it increases dependency between the underlying components.
It creates a problem in the maintenance of the code.

Cyclic Inheritance: A Prohibited Approach While Designing Inheritance In Java

Cyclic Inheritance in Java
Cyclic Inheritance in Java

Cyclic Inheritance:

3 Prohibited Approaches While Designing Inheritance In Java. Cyclic Inheritance is prohibited in java.

class A extends B
{
//do some code
}
class B extends A
{
//do some code
}

let me show one more example

class A extends A{
//do some code
}

For such cases, we are going to get compilation error during compilation but we need to take care while designing this class. It is said the first example of cyclic reference generally occurs while design real-time complex java project.
A second important aspect of java class design, multiple inheritances. This is not supported in java.

class A
{
//some code
}
class B
{
//some code
}
class c extends A,B
{
//some code
}

This is also one kind of Cyclic reference.

Say for this example Class B and Class C is derived from Class A and A is having a method which is overridden in Class B and Class C. Now if a fourth class D trying to extend both the class, by the principle of inheritance both the modified method will come to D. this creates ambiguity for a compiler which one to take.

READ  A Comparison Amongst The Java IDEs: Netbeans vs Eclipse

Secondly by theory, even if D is trying to override all the conflicting methods, then it has to reinvent the wheel. Code redundancy will increase. It will surely destroy the main idea behind an inheritance that is-code reusability.

This diagram is popularly known as the diamond diagram for Multiple inheritances.
Multiple inheritances are not directly supported by java. But by using the interface we can implement the same. A class can not extend more than one class at a time but for an interface, there is no such limitation.
Now, wait for one more concept. Every class in java extends class Object. Class Object is the superclass for all class we create in java. It is the job for the compiler to check and update the .class file accordingly.
Like if you write a class like below:

class A{
//do some activity
}

The java compiler will transform the same into a .class file as…

class A extends Object{
//do some activity
 }

Any class that does not explicitly extend another class implicitly extends object.
This is how java has removed the diamond problem.

READ  Class Throwable in Java

What Is IS-A Relationship And What Are The Rules Of IS-A Relationship In Java?

In java, Inheritance concept came to reduce the number of code line i.e code redundancy. Say in a college we have some student, lecturer, principal. Now for a student, we can have n column, so the corresponding class design will be.

class student{
int id
String name;
int age;
int No_of_Subject;
----
----
student(int id,string name,int age,......)
{
//constructor to initialize the value
this.id=id;
this.name=name;
this.age=age;
----
----
}
}

Similarly, for the lecturer class, we will have…

class lecturer{
int id
String name;
int age;
----
----
lecturer(int id,string name,int age,......)
{
//constructor to initialize the value
this.id=id;
this.name=name;
this.age=age;
----
----
}
}

for principal we will have–

class principal{
int id
String name;
int age;
----
----
principal(int id,string name,int age,......)
{
//constructor to initialize the value
this.id=id;
this.name=name;
this.age=age;
----
----
}
}

now if you observe closely most of the code is redundant. To get reduce redundancy we can create a common class and can derive more special classes from it.

How to design the common class?
It is interesting..we can create a parent class with all the common attribute..the common class is more abstract. And the child classes are more specific class. Child classes can override the methods it got from the parent class. It can also add more instance variable and child-specific method. Instance variables are not overridden because they do not define behaviour. So a subclass can give an inherited instance variable any value
like-

class College_person{
int id
String name;
int age;
----
----
College_person(int id,string name,int age,......)
{
//constructor to initialize the value
this.id=id;
this.name=name;
this.age=age;
----
----
}
}

Now the corresponding classes will become:
Student:

class student extends College_person {
int id
String name;
int age;
----
----
student(int id,string name,int age,......)
{
//constructor to initialize the value
super(id,name,age,......)
this.xyx=xyz;
----
----
}
}

Similarly, for the lecturer class, we will have…

class lecturer extends College_person{
int id
String name;
int age;
----
----
lecturer(int id,string name,int age,......)
{
//constructor to initialize the value
super(id,name,age,......)
this.abc=abc;
----
----
}
}

for principal we will have–

class principal extends College_person{
int id
String name;
int age;
----
----
principal(int id,string name,int age,......)
{
//constructor to initialize the value
super(id,name,age,......)
this.tgb=tgb;
----
----
}
}

If you observe closely the super method is taking care of default value’s initialization and specific values specific to the class are mentioned in the corresponding class. This is inheritance in nature.
the College_person becomes the parent for all class student, lecturer and principal.

READ  Abstract interface ObjectInputValidation in Java

Cool isn’t it???
But to perform a valid parent-child relationship, the relationship has to go through an IS-A test. If it passes then only we can confirm the relationship is perfect.
here is student IS-A College_person? the answer is yes…hence College_person and student are invalid parent-child relationship. Similarly, it is yes for lecturer and principal

So the conclusions are–

  • IS-A relationship is the valid inheritance
  • By using extends keyword we can implement IS-A relationship
  • It reduces the code redundancy but increases code reusability.

Let us see someone more example concerning inheritance:
Class Parent:

Class Parent{
metho1()
{
}
}

Class Child:

Class Child extends Parent{
method2()
{
}

Class test:

Class test{
public static void main(String... Args)
{
//case-1
Parent p=new Parent();
p.method1();
p.method2();
//case-2
Child c=new Child();
c.method1();
c.method2();
//case-3
Parent p=new Child()
p.method1();
p.method2();
//case-4
Child c=new Parent();
c.method1();
c.method2();
}

Let us discuss case by case…
Case-1

Parent p=new Parent();
p.method1();
p.method2();

here Parent class is an independent class hence
p.method1() is a valid method call
but
p.method2() is invalid as in Parent class, method2 is unavailable
so we will get a Compilation error
Error Details:
Can not find symbol
symbol:method method2()
location: Class Parent
Conclusion:
The methods very specific to the child is not available to Parent. So all child-specific methods can not be called with parent reference.
Case-2

Child c=new Child();
c.method1();
c.method2();

As Child class is extending to Parent class hence by default method1 is available to Child class.
hence both the method calls are valid

READ  Class Error in Java

Conclusion:
For the valid parent-child relationship, whatever the parent is having by default will be available to a child
Case-3

Parent p=new Child()
p.method1();
p.method2();

This is interesting…We are creating an object of Child of type Parent.
so p.method1() call is perfectly valid
but
p.method2() we will get a compilation error
Error Details:
can not find symbol
symbol:method method2()
location: Class Parent
Conclusion:
Parent reference can hold child class object but using that variable (reference) we can not call child specific methods. We can only call parent’s methods
Case-4
We will get a compilation error
Error Details:
incompatible types
found Parent
Required Child

How Inheritance Concept Works For Java Enum??

The Enum is treated as a class.

enum Month  
{  
JAN,FEB,MAR;  
//note semicolon(;) is optional here  
}  

will be transferred by the compiler as…

Class Month  
{  
//for JAN  
public static final Month JAN=new Month();  
//similarly for FEB and MAR  
public static final Month FEB=new Month();  
public static final Month MAR=new Month();  
}

Since the underlying concept is class, the very next question arises as can Inheritance concept works for enum? Let us see a few concepts…

  • Every enum is a direct child of java.lang.Enum class in java, So enum can’t extend any other enum
  • Every enum is always final implicitly hence we can’t create child enum

With the above statements, we can conclude that the inheritance concept is not applicable for explicitly. Hence we can’t use extends keyword for enums.

enum x
{}
enum y extends x{}

output: Compile time error

enum x extends java.lan.Enum
{}

output: Compile time error

Class x
{}
enum y extends x{}

output: Compile time error

enum x
{}
Class y extends x{}

output: Compile-time error

Can not inherit from final (enum) or enum types are not extensible

However, an enum can implement any no of interfaces simultaneously.

interface x
{}
enum y implements x{}

Valid deceleration.

Conclusion:
Child reference can not be used to hold the parent class object. The last point is to keep the IS-A direction one way, Child to parent. Java supports Child to parent direction. Not the other way round.Square IS-A shape, but not necessarily Shape IS-A Square.
That’s it for today!!.




Spread the love
Animesh Chatterjeehttps://techtravelhub.com/
I am the founder and owner of the blog - TechTravelHub.com, always love to share knowledge on test automation,tools,techniques and tips.I am a passionate coder of Java and VBScript.I also publish articles on Travel ideas and great honeymoon destinations.Apart from these, I am a gear-head,love to drive across India. I have shared lots of articles here on How to travel several parts of India.Customization of cars aka car modification is my another hobby.Get in touch with me on ani01104@gamil.com

Related Articles

Learn How to Use Jacoco Java code Coverage

Introduction to Jacoco Jacoco provides a wide range of coverage(analysis of instructions,...

Comments

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Recent Posts

Learn Quickly About DevOps Tools in a Fast and Efficient Manner

Introduction to DevOps tools DevOps tools are a collection of...

How to Collaborate between Development and Operations Team Fast and Effectively

Collaborate between Development and Operations Teams are the key...

Learn How to Use Jacoco Java code Coverage

Introduction to Jacoco Jacoco provides a wide range of coverage(analysis...

EDITOR PICKS


Spread the love