0% found this document useful (0 votes)
11 views

UNIT II - JAVA-Inheritance_part

The document discusses the concept of inheritance in Java, explaining its types, such as single, multi-level, hierarchical, and hybrid inheritance, along with the use of the 'super' keyword for accessing superclass methods and constructors. It covers method overriding, dynamic method dispatch, and the order of constructor execution in inheritance scenarios. Additionally, it highlights the advantages of inheritance, particularly code reusability and the ability to create a multi-level hierarchy of classes.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
11 views

UNIT II - JAVA-Inheritance_part

The document discusses the concept of inheritance in Java, explaining its types, such as single, multi-level, hierarchical, and hybrid inheritance, along with the use of the 'super' keyword for accessing superclass methods and constructors. It covers method overriding, dynamic method dispatch, and the order of constructor execution in inheritance scenarios. Additionally, it highlights the advantages of inheritance, particularly code reusability and the ability to create a multi-level hierarchy of classes.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 41

UNIT- II

Inheritance: Basics, Using super, creating a multi level hierarchy, when constructors are
executed, method overriding, polymorphism - dynamic method dispatch, using abstract class,
final with Inheritance, object class.

Inheritance Concept
The inheritance is a very useful and powerful concept of object-oriented programming. In java,
using the inheritance concept, we can use the existing features of one class in another class.
The inheritance provides a great advantage called code re-usability. With the help of code re-
usability, the commonly used code in an application need not be written again and again.

The inheritance can be defined as follows.


The inheritance is the process of acquiring the properties of one class to another class.

1
Inheritance Basics
In inheritance, we use the terms like parent class, child class, base class, derived class,
superclass, and subclass.
The Parent class is the class which provides features to another class. The parent class is also
known as Base class or Superclass.
The Child class is the class which receives features from another class. The child class is also
known as the Derived Class or Subclass.
In the inheritance, the child class acquires the features from its parent class. But the parent class
never acquires the features from its child class.

There are five types of inheritances, and they are as follows.

• Simple Inheritance (or) Single Inheritance


• Multiple Inheritance
• Multi-Level Inheritance
• Hierarchical Inheritance
• Hybrid Inheritance

The following picture illustrates how various inheritances are implemented.

2
The java programming language does not support multiple inheritance type. However, it
provides an alternate with the concept of interfaces.

Creating Child Class in java


In java, we use the keyword extends to create a child class. The following syntax used to create
a child class in java.
Syntax
3
class <ChildClassName> extends <ParentClassName>{
...
//Implementation of child class
...
}

In a java programming language, a class extends only one class. Extending multiple classes is
not allowed in java.

Let's look at individual inheritance types and how they get implemented in java with an
example.

Single Inheritance in java


In this type of inheritance, one child class derives from one parent class. Look at the following
example code.
Example

When we run this code, it produces the following output.

4
Multi-level Inheritance in java
In this type of inheritance, the child class derives from a class which already derived from
another class. Look at the following example java code.

When we run this code, it produce the following output.

5
Hierarchical Inheritance in java
In this type of inheritance, two or more child classes derive from one parent class. Look at the
following example java code.
Example

class ParentClass{
int a;
void setData(int a) {
this.a = a;
}
}

6
class ChildClass extends ParentClass{
void showData() {
System.out.println("Inside ChildClass!");
System.out.println("Value of a is " + a);
}
}
class ChildClassToo extends ParentClass{
void display() {
System.out.println("Inside ChildClassToo!");
System.out.println("Value of a is " + a);
}
}
public class HierarchicalInheritance {

public static void main(String[] args) {

ChildClass child_obj = new ChildClass();


child_obj.setData(100);
child_obj.showData();

ChildClassToo childToo_obj = new ChildClassToo();


childToo_obj.setData(200);
childToo_obj.display();

When we run this code, it produce the following output.

7
Hybrid Inheritance in java
The hybrid inheritance is the combination of more than one type of inheritance. We may use
any combination as a single with multiple inheritances, multi-level with multiple inheritances,
etc.,

8
Java super
The super keyword in Java is used in subclasses to access superclass members
(attributes, constructors and methods).
Before we learn about the super keyword, make sure to know about Java inheritance.

Uses of super keyword


1. To call methods of the superclass that is overridden in the subclass.

2. To access attributes (fields) of the superclass if both superclass and subclass


have attributes with the same name.

3. To explicitly call superclass no-arg (default) or parameterized constructor


from the subclass constructor.

Let’s understand each of these uses.

1. Access Overridden Methods of the superclass


If methods with the same name are defined in both superclass and subclass, the
method in the subclass overrides the method in the superclass. This is called method
overriding.
Example 1: Method overriding

9
class Animal {

// overridden method
public void display(){
System.out.println("I am an animal");
}
}

class Dog extends Animal {

// overriding method
@Override
public void display(){
System.out.println("I am a dog");
}

public void printMessage(){


display();
}
}

class Main {
public static void main(String[] args) {
Dog dog1 = new Dog();
dog1.printMessage();
}
}
Run Code
Output
I am a dog

In this example, by making an object dog1 of Dog class, we can call its method
printMessage() which then executes the display() statement.

10
Since display() is defined in both the classes, the method of subclass Dog overrides
the method of superclass Animal. Hence, the display() of the subclass is called.

What if the overridden method of the superclass has to be called?


We use super.display() if the overridden method display() of
superclass Animal needs to be called.
Example 2: super to Call Superclass Method
class Animal {

// overridden method
public void display(){
System.out.println("I am an animal");
}
}

class Dog extends Animal {

// overriding method
@Override
public void display(){
System.out.println("I am a dog");
}

public void printMessage(){

11
// this calls overriding method
display();

// this calls overridden method


super.display();
}
}

class Main {
public static void main(String[] args) {
Dog dog1 = new Dog();
dog1.printMessage();
}
}
Run Code
Output
I am a dog
I am an animal
Here, how the above program works.

12
2. Access Attributes of the Superclass
The superclass and subclass can have attributes with the same name. We use
the super keyword to access the attribute of the superclass.
Example 3: Access superclass attribute
class Animal {
protected String type="animal";
}

class Dog extends Animal {


public String type="mammal";

public void printType() {


System.out.println("I am a " + type);
System.out.println("I am an " + super.type);
}
}

class Main {
public static void main(String[] args) {
Dog dog1 = new Dog();
dog1.printType();
}
}
Run Code
Output:
I am a mammal
I am an animal

In this example, we have defined the same instance field type in both the
superclass Animal and the subclass Dog.

We then created an object dog1 of the Dog class. Then,


the printType() method is called using this object.
Inside the printType() function,
type refers to the attribute of the subclass Dog.
super.type refers to the attribute of the superclass Animal.

13
Hence, System.out.println("I am a " + type); prints I am a mammal.
And, System.out.println("I am an " + super.type); prints I am an
animal .

3. Use of super() to access superclass constructor


As we know, when an object of a class is created, its default constructor
is automatically called.

To explicitly call the superclass constructor from the subclass


constructor, we use super(). It's a special form of the super keyword.
super() can be used only inside the subclass constructor and must be
the first statement.

Example 4: Use of super()


class Animal {

// default or no-arg constructor of class Animal


Animal() {
System.out.println("I am an animal");
}
}

class Dog extends Animal {

// default or no-arg constructor of class Dog


Dog() {

// calling default constructor of the superclass


super();

System.out.println("I am a dog");
}

14
}

class Main {
public static void main(String[] args) {
Dog dog1 = new Dog();
}
}
Run Code
Output
I am an animal
I am a dog

Here, when an object dog1 of Dog class is created, it automatically calls


the default or no-arg constructor of that class.
Inside the subclass constructor, the super() statement calls the
constructor of the superclass and executes the statements inside it.
Hence, we get the output I am an animal.

The flow of the program then returns back to the subclass constructor and executes
the remaining statements. Thus, I am a dog will be printed.

15
However, using super() is not compulsory. Even if super() is not used in the subclass
constructor, the compiler implicitly calls the default constructor of the superclass.
So, why use redundant code if the compiler automatically invokes super()?
It is required if the parameterized constructor (a constructor that takes
arguments) of the superclass has to be called from the subclass constructor.
The parameterized super() must always be the first statement in the body of the
constructor of the subclass, otherwise, we get a compilation error.

Example 5: Call Parameterized Constructor Using super()


class Animal {

// default or no-arg constructor


Animal() {
System.out.println("I am an animal");
}

// parameterized constructor
Animal (String type) {
System.out.println("Type: "+type);
}
}

class Dog extends Animal {

// default constructor
Dog() {

// calling parameterized constructor of the superclass


super("Animal");

System.out.println("I am a dog");
}
}

class Main {
public static void main(String[] args) {
Dog dog1 = new Dog();
}
}
16
Run Code
Output
Type: Animal
I am a dogThe compiler can automatically call the no-arg constructor. However,
it cannot call parameterized constructors.

If a parameterized constructor has to be called, we need to explicitly define it in the


subclass constructor.

Note that in the above example, we explicitly called the parameterized


constructor super("Animal") . The compiler does not call the default constructor of the
superclass in this case.

Order of Execution of Constructors in Java


Inheritance
Constructors in Java

17
A constructor in Java is similar to a method with a few differences. Constructor has the same
name as the class name. A constructor doesn't have a return type.

A Java program will automatically create a constructor if it is not already defined in the
program. It is executed when an instance of the class is created.

A constructor cannot be static, abstract, final or synchronized. It cannot be overridden.

Java has two types of constructors:

1. Default constructor
2. Parameterized constructor

What is the order of execution of constructor in Java


inheritance?
While implementing inheritance in a Java program, every class has its own constructor.
Therefore, the execution of the constructors starts after the object initialization. It follows a
certain sequence according to the class hierarchy. There can be different orders of execution
depending on the type of inheritance.

Different ways of the order of constructor execution in Java


1. Order of execution of constructor in Single inheritance
In single level inheritance, the constructor of the base class is executed first.

ExOrderSingleInh.java

/* Parent Class */
class ParentClass
{
/* Constructor */
ParentClass()
{
System.out.println("ParentClass constructor executed.");
}
}

/* Child Class */
class ChildClass extends ParentClass
{
/* Constructor */
ChildClass()
{
System.out.println("ChildClass constructor executed.");
}

18
}

public class ExOrderSingleInh


{
/* Driver Code */
public static void main(String ar[])
{
/* Create instance of ChildClass */
System.out.println("Order of constructor execution...");
new ChildClass();
}
}

Output:

Order of constructor execution...


ParentClass constructor executed.
ChildClass constructor executed.

In the above code, after creating an instance of ChildClass the ParentClass constructor is
invoked first and then the ChildClass.

2. Order of execution of constructor in Multilevel inheritance


In multilevel inheritance, all the upper class constructors are executed when an instance of
bottom most child class is created.

ExOrderMultilevel.java

class College
{
/* Constructor */
College()
{
System.out.println("College constructor executed");
}
}

class Department extends College


{
/* Constructor */
Department()
{
System.out.println("Department constructor executed");
}
}

class Student extends Department


{

19
/* Constructor */
Student()
{
System.out.println("Student constructor executed");
}
}
public class ExOrderMultilevel
{
/* Driver Code */
public static void main(String ar[])
{
/* Create instance of Student class */
System.out.println("Order of constructor execution in Multilevel inheritance...");
new Student();
}
}

Output:

Order of constructor execution in Multilevel inheritance...


College constructor executed
Department constructor executed
Student constructor executed

In the above code, an instance of Student class is created and it invokes the constructors
of College, Department and Student accordingly.

3. Calling same class constructor using this keyword


Here, inheritance is not implemented. But there can be multiple constructors of a single class
and those constructors can be accessed using this keyword.

ExecutionOrder.java

public class ExecutionOrder


{
/* Default constructor */
ExecutionOrder()
{
this("CallParam");
System.out.println("Default constructor executed.");
}
/* Parameterized constructor */
ExecutionOrder(String str)
{
System.out.println("Parameterized constructor executed.");
}
/* Driver Code */

20
public static void main(String ar[])
{
/* Create instance of the class */
System.out.println("Order of constructor execution...");
ExecutionOrder obj = new ExecutionOrder();
}
}

Output:

Order of constructor execution...


Parameterized constructor executed.
Default constructor executed.

In the above code, the parameterized constructor is called first even when the default
constructor is called while object creation. It happens because this keyword is used as the first
line of the default constructor.

4. Calling superclass constructor using super keyword


A child class constructor or method can access the base class constructor or method using the
super keyword.

OrderofExecution4.java

/* Parent Class */
class ParentClass
{
int a;
ParentClass(int x)
{
a = x;
}
}

/* Child Class */
class ChildClass extends ParentClass
{
int b;
ChildClass(int x, int y)
{
/* Accessing ParentClass Constructor */
super(x);
b = y;
}
/* Method to show value of a and b */
void Show()
{
System.out.println("Value of a : "+a+"\nValue of b : "+b);
}

21
}

public class OrderofExecution4


{
/* Driver Code */
public static void main(String ar[])
{
System.out.println("Order of constructor execution...");
ChildClass d = new ChildClass(79, 89);
d.Show();
}
}

Output:

Order of constructor execution...


Value of a : 79
Value of b : 89

In the above code, the ChildClass calls the ParentClass constructor using a super keyword
that determines the order of execution of constructors.

Overriding in Java
If you’re a software engineer or developer preparing for a tech interview, and Java is your
preferred programming language, brushing up on the basic concepts will help you solve
problems with more ease. We know that Java is a high-level object-oriented programming
language. It offers many object-oriented properties. Overriding is one of the important features
in Java. In this article, we’ll review what overriding is and how it works:

• What is overriding in Java?


• Overriding vs. overloading in Java
• Rules for Java method overriding
• Java method overriding example
• Method overriding and dynamic method dispatch
• Super keyword in method overriding
• Advantages of method overriding in Java
• FAQs on method overriding in Java

22
What Is Overriding in Java?
In Java, declaring a method in a subclass that is already present in a parent class is
called method overriding. The main purpose of having overridden methods in the child is
having a different implementation for a method that is present in the parent class.

• Overriding method: The method in child class that is the same as a method in the parent class.
• Overridden method: The method in the parent class that is overridden by the child class
method.

Advantages of Method Overriding


• Method overriding helps in writing a generic code based on the parent class.
• It provides multiple implementations of the same method and can be used to invoke parent class
overridden methods using super keyword.
• It defines what behavior a class can have.

Overriding vs. Overloading in Java


Method overriding is used to create a specific implementation of a method that is already
present in the parent class. Method overriding occurs in two classes, where one class inherits
from another class. In overriding, the method return type and function parameters of overriding
and overridden methods must be the same.

Method overloading allows more than one method in a class to have the same name with
different parameters. Basically, we can create multiple methods with the same name in the
same class. However, each method works differently. It makes the program easier to read
(readable).

Here’s a summary of the key differences between overriding and overloading in Java:

23
Rules for Java Method Overriding
• Method name, its function parameters, and the return type of the overriding method and
overridden method must be the same.
• The access modifier of an overriding method cannot be more stringent than the access modifier
of an overridden method.
• Static, Private, and Final methods cannot be overridden because of their scope.
• If the class extends an abstract class or implements an interface, it must override all of the
abstract methods, provided the class itself is not abstract.

Java Method Overriding Example


In the example given below, b is an object of class Topic, and after calling
the b.teach() method, it will execute the method teach() in the Topic class. Here,
class Topic is inherited from the class Java, and both classes have method teach(). But the
method teach() of class Topic overrides the method teach() of class Java; hence after calling
b.teach(), it executes the code inside the teach() method of Topic class.

In the example above, the program will be compiled because the class Topic has its
method teach. Therefore, at the time of execution, it carries on a specific path to the given
object.

Code:

// Class Java
class Java {
// method teach which is overridden method here

24
public void teach() {
System.out.println("Topics in Java");
}
}
// Class Topic
class Topic extends Java {
// method teach which is overriding method here
public void teach() {
System.out.println("Individual topic");
}
}
class Overriding1 {
public static void main(String args[]) {
Java a = new Java(); // Java reference and object
Java b = new Topic(); // Java reference but Topic object
a.teach(); // runs the method in Java class
b.teach(); // runs the method in Topic class
}
}
Output:

Topics in Java

Individual topic

Method Overriding and Dynamic Method Dispatch

In method overriding, during method call in the main function, which method should
be executed (child class or parent class) is determined at runtime by the object type.
The process where the call to the overridden method is resolved at runtime is called
dynamic method dispatch.

Super Keyword in Method Overriding


The super keyword in Java is used for calling the parent class method or constructor. For
example, let’s consider a method named newMethod() in the parent class, then
super.newMethod() can be used to call the newMethod() method of parent class. super() can
be used to call the constructor of the parent class.

So, we can call the overridden method by using the super keyword.

Code:

// Class Java
class Java {
// method teach which is overridden method here

25
public void teach() {
System.out.println("Topics in Java");
}
}
// Class Topic
class Topic extends Java {
// method teach which is overriding method here
public void teach() {
// this will call teach method of Java Class
super.teach();
System.out.println("Individual Topic");
}
}
class Main {
public static void main(String args[]) {
Java a = new Java(); // Java reference and object
Java b = new Topic(); // Java reference but Topic object

a.teach(); // runs the method in Java class


b.teach(); // runs the method in Topic class
}
}
Output:

Topics in Java
Topics in Java
Individual Topic

FAQs on Method Overriding in Java


Question 1: How to prevent overriding a method without using the final modifier in Java?

There are some unusual ways to prevent method overriding in Java. Though the final modifier
is only for that purpose, we can use the private keyword to prevent method overriding. In order
to override a method, the class must be extensible. If we make the constructor of the parent
class private, it is impossible to extend that class because its constructor will not be accessible
in the subclass, which the sub-class constructor automatically invokes. Hence, it is not possible
to override any method from that class.

Question 2: Can we override the constructor in Java?

No. We cannot override constructors in Java because they are not inherited. We can overload
constructs, but we cannot override them. Overriding always happens in the child class, and
since constructors are not inherited, and their name is always the same as the class name, it is
not possible to override them in Java.

Question 3: Can we override the static method?

26
In the case of static methods, there won't be any runtime polymorphism. So, static methods
cannot be overridden. However, if a child class has a defined static method with a similar
signature as the static method of a parent class, then the method in the parent class will be
hidden by the method in the child class.

Polymorphism in Java
What is Polymorphism in Java?
Polymorphism in Java is the task that performs a single action in different ways. So, languages
that do not support polymorphism are not ‘Object-Oriented Languages’, but ‘Object-Based
Languages’. Ada, for instance, is one such language. Since Java supports polymorphism, it
is an Object-Oriented Language.
Polymorphism occurs when there is inheritance, i.e., many classes are related.
Inheritance is a powerful feature in Java. Java Inheritance lets one class acquire the properties
and attributes of another class. Polymorphism in Java allows us to use these inherited properties
to perform different tasks. Thus, allowing us to achieve the same action in many different ways.
What is Polymorphism?
The derivation of the word Polymorphism is from two different Greek words- poly and morphs.
“Poly” means numerous, and “Morphs” means forms. So, polymorphism means innumerable
forms. Polymorphism, therefore, is one of the most significant features of Object-Oriented
Programming.

Polymorphism in Java Example

A superclass named “Shapes” has a method called “area()”. Subclasses of “Shapes” can be
“Triangle”, “circle”, “Rectangle”, etc. Each subclass has its way of calculating area. Using
Inheritance and Polymorphism means, the subclasses can use the “area()” method to find the
area’s formula for that shape.

class Shapes {
public void area() {
System.out.println("The formula for area of ");
}
}
class Triangle extends Shapes {
public void area() {
System.out.println("Triangle is ½ * base * height ");
}
}
class Circle extends Shapes {
public void area() {
System.out.println("Circle is 3.14 * radius * radius ");
}

27
}
class Main {
public static void main(String[] args) {
Shapes myShape = new Shapes(); // Create a Shapes object
Shapes myTriangle = new Triangle(); // Create a Triangle object
Shapes myCircle = new Circle(); // Create a Circle object
myShape.area();
myTriangle.area();
myShape.area();
myCircle.area();
}
}

Output:
The formula for the area of the Triangle is 1/2 * base * height
The formula for the area of the Circle is 3.14 * radius * radius

class Shape {
public void draw() {
System.out.println("Drawing a shape");
}
}

class Circle extends Shape {


@Override
public void draw() {
System.out.println("Drawing a circle");
}
}

class Square extends Shape {


@Override
public void draw() {
System.out.println("Drawing a square");
}
}

class Main {
public static void main(String[] args) {
Shape s1 = new Circle();
Shape s2 = new Square();

s1.draw(); // Output: "Drawing a circle"


s2.draw(); // Output: "Drawing a square"
}
}
In this example, we have a base class Shape with a single method draw() that prints “Drawing
a shape” to the console. We then create two subclasses, Circle and Square, that override
the draw() method to print “Drawing a circle” and “Drawing a square” respectively.

28
In the main method, we create two instances of the Shape class, s1 and s2, which are actually
instances of the Circle and Square subclasses. When we call the draw() method on these
objects, the correct implementation is called based on the actual type of the object, this is run-
time polymorphism. The program will output: “Drawing a circle” and “Drawing a square”

In this example, the draw() method is overridden in the subclasses, and this allows for the
program to determine which method to use at runtime. This is known as runtime polymorphism
or dynamic polymorphism, Because at runtime the JVM determines the actual type of the object
and calls the corresponding method.

Types of Polymorphism
You can perform Polymorphism in Java via two different methods:

1. Method Overloading
2. Method Overriding

What is Method Overloading in Java?

Method overloading is the process that can create multiple methods of the same name in the
same class, and all the methods work in different ways. Method overloading occurs when there
is more than one method of the same name in the class.

Example of Method Overloading in Java

class Shapes {
public void area() {
System.out.println("Find area ");
}
public void area(int r) {
System.out.println("Circle area = "+3.14*r*r);
}

public void area(double b, double h) {


System.out.println("Triangle area="+0.5*b*h);
}
public void area(int l, int b) {
System.out.println("Rectangle area="+l*b);
}
}

class Main {
public static void main(String[] args) {
Shapes myShape = new Shapes(); // Create a Shapes object

myShape.area();
myShape.area(5);

29
myShape.area(6.0,1.2);
myShape.area(6,2);

}
}
Output:

Find area
Circle area = 78.5
Triangle area=3.60
Rectangle area=12

What is Method Overriding in Java?

Method overriding is the process when the subclass or a child class has the same method as
declared in the parent class.

Example of Method Overriding in Java


class Vehicle{
//defining a method
void run(){System.out.println("Vehicle is moving");}
}
//Creating a child class
class Car2 extends Vehicle{
//defining the same method as in the parent class
void run(){System.out.println("car is running safely");}

public static void main(String args[]){


Car2 obj = new Car2();//creating object
obj.run();//calling method
}
}
Output:

Car is running safely

Also, Polymorphism in Java can be classified into two types, i.e:

1. Static/Compile-Time Polymorphism
2. Dynamic/Runtime Polymorphism

What is Compile-Time Polymorphism in Java?

Compile Time Polymorphism In Java is also known as Static Polymorphism. Furthermore,


the call to the method is resolved at compile-time. Compile-Time polymorphism is achieved
through Method Overloading. This type of polymorphism can also be achieved
through Operator Overloading. However, Java does not support Operator Overloading.

30
Method Overloading is when a class has multiple methods with the same name, but the number,
types, and order of parameters and the return type of the methods are different. Java allows the
user freedom to use the same name for various functions as long as it can distinguish between
them by the type and number of parameters. Check out some of the important questions on run
time polymorphism in java interview questions.

Example of Compile-Time Polymorphism in Java

We will do addition in Java and understand the concept of compile time polymorphism using
subtract()

public class Addition


{
void sum(int a, int b)
{
int c = a+b;
System.out.println(“ Addition of two numbers :” +c); }
void sum(int a, int b, int e)
{
int c = a+b+e;
System.out.println(“ Addition of three numbers :” +c); }
public static void main(String[] args)
{
Addition obj = new Addition();
obj.sum ( 30,90);
obj.sum(45, 80, 22);
}
}

The output of the program will be:

Sum of two numbers: 120


Sum of three numbers: 147
In this program, the sum() method overloads with two types via different parameters.

This is the basic concept of compile-time polymorphism in java where we can perform various
operations by using multiple methods having the same name.

What is Runtime Polymorphism in Java?

Runtime polymorphism in Java is also popularly known as Dynamic Binding or Dynamic


Method Dispatch. In this process, the call to an overridden method is resolved dynamically at
runtime rather than at compile-time. You can achieve Runtime polymorphism via Method
Overriding.

Method Overriding is done when a child or a subclass has a method with the same name,
parameters, and return type as the parent or the superclass; then that function overrides the

31
function in the superclass. In simpler terms, if the subclass provides its definition to a method
already present in the superclass; then that function in the base class is said to be overridden.

Also, it should be noted that runtime polymorphism can only be achieved through functions
and not data members.

Overriding is done by using a reference variable of the superclass. The method to be called is
determined based on the object which is being referred to by the reference variable. This is also
known as Upcasting.

Upcasting takes place when the Parent class’s reference variable refers to the object of the child
class. For example:

class A{}
class B extends A{}
A a=new B(); //upcasting

Examples of Runtime Polymorphism in Java

Example 1:

In this example, we are creating one superclass Animal and three subclasses, Herbivores,
Carnivores, and Omnivores. Subclasses extend the superclass and override its eat() method.
We will call the eat() method by the reference variable of Parent class, i.e. Animal class. As it
refers to the base class object and the base class method overrides the superclass method; the
base class method is invoked at runtime. As Java Virtual Machine or the JVM and not the
compiler determines method invocation, it is, therefore, runtime polymorphism.

class Animal{
void eat(){
System.out.println("Animals Eat");
}
}
class herbivores extends Animal{
void eat(){
System.out.println("Herbivores Eat Plants");
}
}
class omnivores extends Animal{
void eat(){
System.out.println("Omnivores Eat Plants and meat");
}
}
class carnivores extends Animal{
void eat(){
System.out.println("Carnivores Eat meat");
}
}

32
class main{
public static void main(String args[]){
Animal A = new Animal();
Animal h = new herbivores(); //upcasting
Animal o = new omnivores(); //upcasting
Animal c = new carnivores(); //upcasting
A.eat();
h.eat();
o.eat();
c.eat();

}
}
Output:

Animals eat
Herbivores Eat Plants
Omnivores Eat Plants and meat
Carnivores eat meat

Example 2:

In this example, we are creating one superclass Hillstations and three subclasses Manali,
Mussoorie, Gulmarg. Subclasses extend the superclass and override its location() and
famousfor() method. We will call the location() and famousfor() method by the Parent class’,
i.e. Hillstations class. As it refers to the base class object and the base class method overrides
the superclass method; the base class method is invoked at runtime. Also, as Java Virtual
Machine or the JVM and not the compiler determines method invocation, it is runtime
polymorphism.

class Hillstations{
void location(){
System.out.println("Location is:");
}
void famousfor(){
System.out.println("Famous for:");
}

}
class Manali extends Hillstations {
void location(){
System.out.println("Manali is in Himachal Pradesh");
}
void famousfor(){
System.out.println("It is Famous for Hadimba Temple and adventure sports");
}
}
class Mussoorie extends Hillstations {
void location(){
System.out.println("Mussoorie is in Uttarakhand");

33
}
void famousfor(){
System.out.println("It is Famous for education institutions");
}
}
class Gulmarg extends Hillstations {
void location(){
System.out.println("Gulmarg is in J&K");
}
void famousfor(){
System.out.println("It is Famous for skiing");
}
}
class main{
public static void main(String args[]){
Hillstations A = new Hillstations();
Hillstations M = new Manali();

Hillstations Mu = new Mussoorie();

Hillstations G = new Gulmarg();

A.location();
A.famousfor();

M.location();
M.famousfor();

Mu.location();
Mu.famousfor();

G.location();
G.famousfor();
}
}
Output:

Location is:
Famous for:
Manali is in Himachal Pradesh
It is Famous for Hadimba Temple and adventure sports
Mussoorie is in Uttarakhand
It is Famous for education institutions
Gulmarg is in J&K
It is Famous for skiing

Example of run-time polymorphism in java

We will create two classes Car and Innova, Innova class will extend the car class and will
override its run() method.

34
class Car
{
void run()
{
System.out.println(“ running”);
}
}
class innova extends Car
{
void run();
{
System.out.println(“ running fast at 120km”);
}
public static void main(String args[])
{
Car c = new innova();
c.run();
}
}
The output of the following program will be;
Running fast at 120 km.
Another example for run-time polymorphism in Java
Now, let us check if we can achieve runtime polymorphism via data members.
class car
{
int speedlimit = 125;
}
class innova extends car
{
int speedlimit = 135;
public static void main(String args[])
{
car obj = new innova();
System.out.println(obj.speedlimit);
}
The output of the following program will be :
125
This clearly implies we can’t achieve Runtime polymorphism via data members. In short, a method is
overridden, not the data members.
Runtime polymorphism with multilevel inheritance
class grandfather
{
void swim()
{
System.out.println(“ Swimming”);
}
}
class father extends grandfather
{
void swim()
{
System.out.println(“ Swimming in river”);
}

35
}
class son extends father
{
void swim()
{
System.out.println(“ Swimming in pool”);
}
public static void main(String args[])
{
grandfather f1,f2,f3;
f1 =new grandfather();
f2 = new father();
f3 = new son();
f1.swim();
f2.swim();
f3.swim():
}
}
The output of the following program will be:
Swimming, Swimming in river, Swimming in pool
Another runtime polymorphism with multilevel inheritance example
class soundAnimal
{
public void Sound()
{
System.out.println("Different sounds of animal"); }
}
class buffalo extends soundAnimal
{
public void Sound()
{
System.out.println("The buffalo sound- gho,gho"); }
}
class snake extends soundAnimal
{
public void Sound()
{
System.out.println("The snake sound- his,his"); }
}
class tiger extends soundAnimal
{
public void Sound()
{
System.out.println("The tiger sounds- roooo, rooo"); }
}
public class Animal Main
{
public static void main(String[] args)
{
soundAnimal Animal = new soundAnimal(); soundAnimal buffalo = new buffalo();
soundAnimal snake = new snake();
soundAnimal tiger = new tiger();

36
Animal.Sound();
buffalo.Sound();
snake.Sound();
tiger.Sound();
}
}
The output of the following program will be;
The buffalo sound- gho,gho
The snake sound- his,his
The tiger sound- roooo,roooo

We hope you got an idea about runtime and compile-time polymorphism.

Polymorphic Subtypes
Subtype basically means that a subtype can serve as another type’s subtype, sounds a bit
complicated?

Let’s understand this with the help of an example:

Assuming we have to draw some arbitrary shapes, we can introduce a class named ‘shape’ with
a draw() method. By overriding draw() with other subclasses such as circle, square, rectangle,
trapezium, etc we will introduce an array of type ‘shape’ whose elements store references will
refer to ‘shape’ subclass references. Next time, we will call draw(), all shapes instances draw
() method will be called.

This Subtype polymorphism generally relies on upcasting and late binding. A casting where
you cast up the inheritance hierarchy from subtype to a supertype is termed upcasting.

To call non-final instance methods we use late binding. In short, a compiler should not perform
any argument checks, type checks, method calls, etc, and leave everything on the runtime.

What is Polymorphism in Programming?


Polymorphism in programming is defined usage of a single symbol to represent multiple
different types.
What is Polymorphism Variables?
A polymorphic variable is defined as a variable that can hold values of different types
during the course of execution.
Why use Polymorphism in Java?
Polymorphism in Java makes it possible to write a method that can correctly process lots of
different types of functionalities that have the same name. We can also gain consistency in
our code by using polymorphism.
Advantages of Polymorphism in Java
It provides reusability to the code. The classes that are written, tested and implemented can be
reused multiple times. Furthermore, it saves a lot of time for the coder. Also, the one can
change the code without affecting the original code.

37
A single variable can be used to store multiple data values. The value of a variable you inherit
from the superclass into the subclass can be changed without changing that variable’s value in
the superclass; or any other subclasses.
With lesser lines of code, it becomes easier for the programmer to debug the code.
Characteristics of Polymorphism
Polymorphism has many other characteristics other than Method Overloading and Method
Overriding. They include:
Coercion
Internal Operator Overloading
Polymorphic Variables or Parameters
1. Coercion
Coercion deals with implicitly converting one type of object into a new object of a different
kind. Also, this is done automatically to prevent type errors in the code.
Programming languages such as C, java, etc support the conversion of value from one data
type to another data type. Data type conversions are of two types, i.e., implicit and explicit.
Implicit type conversion is automatically done in the program and this type of conversion is
also termed coercion.
For example, if an operand is an integer and another one is in float, the compiler implicitly
converts the integer into float value to avoid type error.
Example:
class coercion {

public static void main(String[] args) {


Double area = 3.14*5*7;
System.out.println(area);
String s = "happy";
int x=5;
String word = s+x;
System.out.println(word);

}
}
Output:
109.9
happy5

2. Internal Operator Overloading


In Operator Overloading, an operator or symbol behaves in more ways than one depending
upon the input context or the type of operands. It is a characteristic of static polymorphism.
Although Java does not support user-defined operator overloading like C++, where the user
can define how an operator works for different operands, there are few instances where Java
internally overloads operators.
Operator overloading is the concept of using the operator as per your choice. Therefore, an
operator symbol or method name can be used as a ‘user-defined’ type as per the
requirements.
For example, ‘+’ can be used to perform the addition of numbers (same data type) or for
concatenation of two or more strings.
In the case of +, can be used for addition and also for concatenation.
For example:
class coercion {

38
public static void main(String[] args) {

String s = "happy";
String s1 = "world";
int x=5;
int y=10;

System.out.println(s+s1);
System.out.println(x+y);

}
}
Output :
happyworld
15
Similarly, operators like! &, and | are also in the overload position for logical and bitwise
operations. In both of these cases, the type of argument will decide how the operator will
interpret.
3. Polymorphic Variables or Parameters
In Java, the object or instance variables represent the polymorphic variables. This is because
any object variables of a class can have an IS-A relationship with their own classes and
subclasses.
The Polymorphic Variable is a variable that can hold values of different types during the time
of execution.
Parametric polymorphism specifies that while class declaration, a field name can associate
with different types, and a method name can associate with different parameters and return
types.
For example:
class Shape
{
public void display()
{
System.out.println("A Shape.");
}
}
class Triangle extends Shape
{
public void display()
{
System.out.println("I am a triangle.");
}
}
class Main{
public static void main(String[] args)
{
Shape obj;
obj = new Shape();
obj.display();
obj = new Triangle();

39
obj.display();
}
}
Output:
A Shape.
I am a triangle.

Here, the obj object is a polymorphic variable. This is because the superclass’s same object
refers to the parent class (Shape) and the child class (Triangle).

Problems with Polymorphism

With lots of advantages, there are also a few disadvantages of polymorphism.


Polymorphism is quite challenging while implementation.
It tends to reduce the readability of the code.
It raises some serious performance issues in real-time as well.

Type Identification During Downcasting

Downcasting is termed as casting to a child type or casting a common type to an individual


type. So, we use downcasting whenever we need to access or understand the behaviour of the
subtypes.

Example,

This is a hierarchical example

Food> Vegetable> Ladyfinger, Tomato

Here, tomato and ladyfinger are two subclasses.

In downcasting, we narrow the type of objects, which means we are converting common type
to individual type.

Vegetable vegetable = new Tomato();

Tomato castedTomato = (Tomato) vegetable;

Here we are casting common type to an individual type, superclass to subclass which is not
possible directly in java.

We explicitly tell the compiler what the runtime type of the object is.

Fragile base class problem

Fragile base class problem is nothing but a fundamental architectural problem.


Sometimes the improper design of a parent class can lead a subclass of a superclass to use
superclass in some unpredicted ways.
The fragility of inheritance will lead to broken codes even when all the criteria is met.

40
This architectural problem is termed as a fragile base class problem in object-oriented
programming systems and language.
Basically, the reason for the fragile base problem is that the developer of the base class has no
idea of the subclass design. There is no solution yet for this problem.

41

You might also like