Java Polymorphism Notes
Java Polymorphism Notes
• Compile-Time Polymorphism
Compile time polymorphism in Java is also known as early binding or static polymorphism. The binding is
performed during compilation time and hence the name compile-time polymorphism. Binding refers to
connecting the function call to the function body. It is achieved by overloading methods, and by changing
the signature of the function. The term signature of function refers to parameters and their types along
with the return value and its type. It defines the input and output of a function.
Example:
Overloading by passing different number of arguments
class CompileTime {
// perimeter method with a single argument
static int perimeter(int a) {
return 4 * a;
}
// perimeter method with two arguments (overloading)
static int perimeter(int l, int b) {
return 2 * (l + b);
}
}
class Polymorphism {
public static void main(String[] args) {
// calling perimeter method by passing a single argument
System.out.println("Side of square : 4\nPerimeter of square will be : " + Compiletime.perimeter(4) +
"\n");
// calling perimeter method by passing two arguments
System.out.println("Sides of rectangle are : 10, 13\nPerimeter of rectangle will be : " +
Compiletime.perimeter(10, 13));
}
}
Overloading by different types of argument to the function.
class Compiletime{
// contact method, which takes two arguments String and long
static void contact(String fname, long number) {
System.out.println("Name : "+fname+"\nNumber : "+number);
}
// contact method, which takes two arguments and both are Strings (overloading)
static void contact(String fname, String mailid) {
System.out.println("Name : "+fname+"\nEmail : "+mailid);
}
}
class Polymorphism{
public static void main(String[] args) {
// calling first contact method
Compiletime.contact("Soham", 1234567890);
System.out.print("\n");
// calling second contact method
Compiletime.contact("Soham", "soham@mail.com");
}
}
• Runtime Polymorphism
Runtime polymorphism is also called dynamic method dispatch. Instead of resolving the overridden
method at compile-time, it is resolved at runtime. Here, an overridden child class method is called
through its parent's reference. Then the method is called according to the type of object. In runtime, JVM
figures out the object type and the method belonging to that object.
Runtime polymorphism in Java occurs when we have two or more classes, and all are interrelated through
inheritance. To achieve runtime polymorphism, we must build an "IS-A" relationship between classes and
override a method.
Method overriding
If a child class has a method as its parent class, it is called method overriding. If the derived class has a
specific implementation of the method that has been declared in its parent class is known as method
overriding.
Rules for overriding a method in Java:
What is an Interface?
Final Variables
When a variable is declared with the final keyword, its value can’t be modified, essentially, a constant.
This also means that you must initialize a final variable. If the final variable is a reference, this means that
the variable cannot be re-bound to reference another object, but the internal state of the object pointed
by that reference variable can be changed i.e. you can add or remove elements from the final array or
final collection. It is good practice to represent final variables in all uppercase, using underscore to
separate words.
We must initialize a final variable, otherwise, the compiler will throw a compile-time error. A final variable
can only be initialized once, either via an initializer or an assignment statement. There are three ways to
initialize a final variable:
You can initialize a final variable when it is declared. This approach is the most common. A final variable
is called a blank final variable if it is not initialized while declaration.
A blank final variable can be initialized inside an instance-initializer block or inside the constructor. If you
have more than one constructor in your class then it must be initialized in all of them, otherwise, a
compile-time error will be thrown.
A blank final static variable can be initialized inside a static block.
Let us see these two different ways of initializing a final variable:
// Java Program to demonstrate Different Ways of Initializing a final Variable
// Main class
class GFG {
final int THRESHOLD = 5; // a final variable direct initialize
final int CAPACITY; // a blank final variable
final int MINIMUM; // another blank final variable
static final double PI = 3.141592653589793; // a final static variable PI direct initialize
static final double EULERCONSTANT; // a blank final static variable
// instance initializer block for initializing CAPACITY
{
CAPACITY = 25;
}
// static initializer block for initializing EULERCONSTANT
static{
EULERCONSTANT = 2.3;
}
// constructor for initializing MINIMUM
// Note that if there are more than one constructor, you must initialize MINIMUM in them also
public GFG()
{
MINIMUM = -1;
}
}
When to use a final variable?
The only difference between a normal variable and a final variable is that we can re-assign the value to a
normal variable but we cannot change the value of a final variable once assigned. Hence final variables
must be used only for the values that we want to remain constant throughout the execution of the
program.
Example 1:
// Java Program to Demonstrate Re-assigning final Variable will throw Compile-time Error
// Main class
Class Main {
// Declaring and customly initializing static final variable
static final int CAPACITY = 4;
// Main driver method
public static void main(String args[])
{
// Re-assigning final variable will throw compile-time error
CAPACITY = 5;
}
}
4. Creating and using Interfaces
What is an Interface?
An Interface in Java programming language is defined as an abstract type used to specify the behavior of a
class. A Java interface contains static constants and abstract methods. A class can implement multiple
interfaces. In Java, interfaces are declared using the interface keyword. All methods in the interface are
implicitly public and abstract.
We will define an interface using the interface keyword as shown below −
interface MyInterface{
public void display();
public void setName(String name);
public void setAge(int age);
}
Purpose of the interface
• Provides communication: One of the uses of the interface is to provide communication. Through
interface you can specify how you want the methods and fields of a particular type.
• Multiple inheritance: Java doesn’t support multiple inheritance, using interfaces you can achieve
multiple inheritance
• Abstraction: Abstraction is a process of hiding the implementation details from the user, only the
functionality will be provided to the user. In other words, the user will have the information on what
the object does instead of how it does it. Since all the methods of the interface are abstract and user
doesn’t know how a method is written except the method signature/prototype. Using interfaces, you
can achieve (complete) abstraction.
• Loose coupling: Coupling refers to the dependency of one object type on another, if two objects are
completely independent of each other and the changes done in one doesn’t affect the other both are
said to be loosely coupled.
Example 1:
public interface Vehicle {
public void start();
public void stop();
}
class Car implements Vehicle {
public void start() {
System.out.println("starting car engine...");
}
public void stop() {
System.out.println("stopping car engine...");
}
}
class Truck implements Vehicle {
public void start() {
System.out.println("starting truck engine...");
}
public void stop() {
System.out.println("stopping truck engine...");
}
}
public class InterfaceExample {
public static void main(String[] args)
{
Vehicle tesla = new Car();
tesla.start();
tesla.stop();
Vehicle tata = new Truck();
tata.start();
tata.stop();
}
}
Example 2: Loose Coupling
interface Keyboard
{
String display();
}
class DellKeyboard implements Keyboard
{
String info;
public String display()
{
this.info = "the Dell keyboard.";
return this.info;
}
}
class LenovoKeyboard implements Keyboard
{
String info;
public String display()
{
this.info = "the Lenovo keyboard.";
return this.info;
}
}
class Computer
{
// the method is now dependent on the interface Keyboard
public void keyboardUsed(Keyboard k)
{
System.out.println("The computer is using " + k.display());
}
}
public class CouplingExample
{
// main method
public static void main(String args[])
{
// creating an object of the class Computer
Computer obj = new Computer();
// creating an object of the class LenovoKeyboard
LenovoKeyboard lk = new LenovoKeyboard();
obj.keyboardUsed(lk);
Example 3: The Java program that demonstrates multiple interfaces is shown below.
//Interface_One declaration
interface Interface_One{
void print();
}
//Interface_Two declaration
interface Interface_Two{
void show();
}
//multiple inheritance - DemoClass implementing Interface_One and Interface_Two
class DemoClass implements Interface_One,Interface_Two{
public void print(){ //Override Interface_One print()
System.out.println("Democlass::Interface_One_Print ()");
}
public void show(){ //Override Interface_Two show()
System.out.println("DemoClass::Interface_Two_Show ()");
}
}
public class Main{
public static void main(String args[]){
DemoClass obj = new DemoClass(); //create DemoClass object and call methods
obj.print();
obj.show();
}
}
Example 4: The Java program to implement interface inheritance is shown below.
//Interface_One declaration
interface Interface_One{
void print();
}
//Interface_Two declaration; inherits from Interface_One
interface Interface_Two extends Interface_One{
void show();
}
//multiple inheritance - DemoClass implementing Interface_Two
class DemoClass implements Interface_Two{
public void print(){ //Override Interface_Two print()
System.out.println("Democlass
public class Main{
public static void main(String args[]){
DemoClass obj = new DemoClass(); //create DemoClass object and call methods
obj.print();
obj.show();
}
}
Lab Work
Program 1. Overloading by changing the number of parameters in the argument
class MethodOverloading {
// overloading of method which takes single int object as a parameter
private static void display(int a){
System.out.println("One Arguments: " + a);
}
// method which takes two object or parameters
private static void display(int a, int b){
System.out.println("Two Arguments: " + a + " and " + b);
}
// main method
public static void main(String[] args) {
// calling display function by passing one parameter: method 1 is called
display(2);
// calling display function by passing two parameter: method 2 is called
display(2, 4);
}
}
Program 2. By changing Datatype of parameter
class MethodOverloading {
// this method accepts int datatype
private static void display(int a){
System.out.println("Got Int data.");
}
// this method accepts String object
private static void display(String a){
System.out.println("Got String object.");
}
public static void main(String[] args) {
display(4);
display("Hello");
}
}
Program 3. By changing the sequence of parameters
class Student{
// Method 1
public void stuIdentity(String name, int id)
{
// Printing name and id of student
System.out.println("stuName :" + name + " " + "Id :" + id);
}
// Method 2
public void stuIdentity(int id, String name)
{
// Again printing name and id of person
System.out.println("Id :" + id + " "+ "stuName :" + name);
}
}
// Class 2
// Main class
class Main {
// Main driver method
public static void main(String[] args)
{
// Creating object of above class
Student stu= new Student(); // Passing name and id // Reversing order
stu.stuIdentity("Mohit", 1);
stu.stuIdentity(2, "shubham");
}
}
Program 3. Overriding example1
// parent class Shape
class Shape{
// creating area method
void area(){
System.out.println("Formula for areas.");
}
}
// Square class extends Shape class
class Square extends Shape{
// overriding area method
void area(){
System.out.println("Area of square : a * a");
}
}
// Rectangle class extends Shape class
class Rectangle extends Shape{
// overriding area method
void area(){
System.out.println("Area of rectangle : 2 * (a + b)");
}
}
// Circle class extends Shape class
class Circle extends Shape{
// overriding area method
void area(){
System.out.println("Area of circle : pi * r * r");
}
}
class Polymorphism{
public static void main(String[] args) {
// creating new object of Shape class
Shape S = new Shape();
S.area();
S = new Square();
S.area();
S = new Rectangle();
S.area();
S = new Circle();
S.area();
}
}
Program 4. Overriding example2
// parent class Bank
class Bank{
// creating rateOfInterest method
float rateOfInterest(){
return 0;
}
}
// ICICI class extends Bank class
class ICICI extends Bank{
// overriding rateOfInterest method
float rateOfInterest(){
return 5.5f;
}
}
// SBI class extends Bank class
class SBI extends Bank{
// overriding rateOfInterest method
float rateOfInterest(){
return 10.6f;
}
}
// HDFC class extends Bank class
class HDFC extends Bank{
// overriding rateOfInterest method
float rateOfInterest(){
return 9.4f;
}
}
class Polymorphism{
public static void main(String[] args) {
// creating variable of Bank class
Bank B;
B = new ICICI();
System.out.println("Rate of interest of ICICI is:"+B.rateOfInterest());
B = new SBI();
System.out.println("Rate of interest of SBI is: "+B.rateOfInterest());
B = new HDFC();
System.out.println("Rate of interest of HDFC is: "+B.rateOfInterest());
}
}
Program 5. Implementation of Abstract Class
//Example of an abstract class that has abstract and non-abstract methods
abstract class Bike{
Bike()
{
System.out.println("bike is created");
}
abstract void run(); //abstract method that need to be overriden
void changeGear() //non-abstract method
{
System.out.println("gear changed");
}
}
//Creating a Child class which inherits Abstract class
class Honda extends Bike{
void run()
{
System.out.println("Bike running safely..");
}
}
//Creating a Test class which calls abstract and non-abstract methods
class TestAbstraction{
public static void main(String args[]){
Bike obj = new Honda();
obj.run();
obj.changeGear();
}
}
Program 6. Implementation of Interface
import java.io.*;
interface Vehicle {
// all are the abstract methods.
void changeGear(int a);
void speedUp(int a);
void applyBrakes(int a);
}
class Bicycle implements Vehicle{
int speed;
int gear;
// to change gear
@Override
public void changeGear(int newGear){
gear = newGear;
}
// to increase speed
@Override
public void speedUp(int increment){
speed = speed + increment;
}
// to decrease speed
@Override
public void applyBrakes(int decrement){
speed = speed - decrement;
}
public void printStates() {
System.out.println("speed: " + speed + " gear: " + gear);
}
}
class Bike implements Vehicle {
int speed;
int gear;
// to change gear
@Override
public void changeGear(int newGear){
gear = newGear;
}
// to increase speed
@Override
public void speedUp(int increment){
speed = speed + increment;
}
// to decrease speed
@Override
public void applyBrakes(int decrement){
speed = speed - decrement;
}
public void printStates() {
System.out.println("speed: " + speed + " gear: " + gear);
}
}
class Main {
public static void main (String[] args) {
// creating an instance of Bicycle doing some operations
Bicycle bicycle = new Bicycle();
bicycle.changeGear(2);
bicycle.speedUp(3);
bicycle.applyBrakes(1);
System.out.println("Bicycle present state :");
bicycle.printStates();
inprotected.com