Monday, June 1, 2020

OOPS Concept - Ploymorphism

Polymorphism: Polymorphism is the property of an object which allows it to take multiple form.
Polymorphism = Poly == multiple, morph == forms

Types of polymorphism:
  1. Compile Time Polymorphism or Static Polymorphism, Example: Method Overloading
  2. Run time polymorphism or Dynamic Polymorphism, Example: Method Overriding
OverloadingOverriding
  • Share the same name with different parameters
  • Occurs during compile time
  • Happens within the same class
  • Share the same name and same parameters
  • occurs during Run time
  • Happens between parent class and child class

  • Overloading: Two methods are said to be overloaded if and only if both methods have same name but different signature (argument types or input). It happens within the same class.
Example:
class Test{
       public void m1(int i) {
             
       }
       public void m1(long l) {
             
       }
}
II: Example
package com.cerotid.oo.principles;
class Test{
       void m1(int a) {
             System.out.println("int a m1 method");
       }
       void m1(int a, int b) {
             System.out.println("int a int b m1 method");
       }
       void m1(char ch) {
             System.out.println("char m1 method");
       }
}
public class OverloadingDemo {
       public static void main(String[] args) {
             Test t = new Test();
             t.m1(10);
             t.m1(10, 20);
             t.m1('a');
       }
}
Output: 
int a m1 method
int a int b m1 method
char m1 method

Overriding: Whatever methods parent has, by default available to the child through inheritance. Some times child may not satisfy with parent method implementation. Then, child is allow to redefine that method with the same method name and parameters but different implementation in the child class . This process is called overriding.
  • Methods having same name and same argument in parent class and child class is known as overriding. 
  • The parent method which is overridden is called overridden method
  • The child method which is overriding is called overriding method
  • In overloading, same method name but different parameters and in overriding, same method name as well as same parameters
class Human{
//Overridden method
public void eat()
{
System.out.println("Human is eating");
}}class Boy extends Human{
//Overriding method
public void eat(){
System.out.println("Boy is eating");
}
public static void main( String args[]) {
Boy obj = new Boy();
//This will call the child class version of eat()
obj.eat();
}}
Output: Boy is eating

 8 Rules in overridden:
While overriding method, overridden method signature and overriding method signature must be same
Example I:
class Vehicle {
       void run() {
             System.out.println("Vehicle is running");
       }
}
class Bike extends Vehicle{
       void run(){
             System.out.println("Bike is running");
       }
}
public class OverridingDemo3 {
public static void main(String[] args) {
       Bike bk = new Bike();
       bk.run();
}
}
Output:
Bike is running

Example II:
class Animal1{
       public void whoAmI() {// overridden method signature        
             System.out.println("I am an Animal1");
       }
       
}
class Horse extends Animal1{
       public void whoAmI() { //overriding method signature
             System.out.println("I am a horse");
       }
}
public class OverridingDemo {
public static void main(String[] args) {
       Animal1 a = new Animal1();           //Animal1 reference and Animal1 object
       Animal1 h = new Horse();            //Animlal1 reference but Horse object
       Horse h1 = new Horse();            //Horse reference and Horse object
       a.whoAmI();                        //runs the method in Animal1 class
       h.whoAmI();                       //runs the method in Horse class
       h1.whoAmI();                     // runs method in Horse class
}
}
Output:
I am an Animal1
I am a horse
I am a horse
Example III:
class Company{
       void address() {
             System.out.println("Company address");
       }
}
class Amazon extends Company{
       void address() {
             //super.address();//invokes the parent class method (i.e. represents parent class method)
             System.out.println("Amazon address");
       }
}
public class OverridingDemo2 {
public static void main(String[] args) {
       Company a = new Company();       // parent class reference variable and parent object
       Company b = new Amazon();       //parent class reference variable and child object
       Amazon c = new Amazon();       //child class reference variable and child object
       a.address();                  // gives company address only
       b.address();                 // gives Amazon address only
    c.address();                   //gives Amazon address only
}
}
Output:
Company address
Amazon address
Amazon address

While overriding method, overridden method return type and overriding method return type must be the same at primitive level
Example I:
class Vehicle {
       int run() {             // method vs returning primitives
             System.out.println("Vehicle is running");
             return 70;
       }
}
class Bike extends Vehicle{
       int run(){
             System.out.println("Bike is running");
             return 90;
       }
}
public class OverridingDemo3 {
public static void main(String[] args) {
       Bike bk = new Bike();
       bk.run();
}
}
Output: bike is running

It is possible to change the method return type at class level by using co-variant return type
class Animal{}
class Dog extends Animal{}
class Parent{
       Animal marry(){
             System.out.println("marry a black girl");
             Animal a = new Animal();
             return a;
             //return new Animal();
       }
}
class Child extends Parent{
       Dog marry(){                //return type, Dog is child class of Animal 
             System.out.println("marry a red girl");
             return new Dog();
       }
}
public class CovarientReturnTypeDemo {
public static void main(String[] args) {
       new Child().marry();
}
}
Output:
marry a red girl
  • It is not possible to override the final method
  • Static methods are bonds with class and it is not possible to override the static method. This is called method hiding concept.
  • Instance methods are bond with object and it is possible to override the instance methods
  • Private methods are specific to class and not visible to outside class . It is not possible to override the private method 
  • While overriding, it is possible to maintain same level or increase the permission but not possible to reduce the permission

Advantage of method overriding

The main advantage of method overriding is that the class can give its own specific implementation to a inherited method without even modifying the parent class code.

This is helpful when a class has several child classes, so if a child class needs to use the parent class method, it can use it and the other classes that want to have different implementation can use overriding feature to make changes without touching the parent class code.
Example I:
package com.cerotid.oo.principles;
class Vehicle {
       void run() {
             System.out.println("Vehicle is running");
       }
}
class Bike extends Vehicle{
       void run(){
             System.out.println("Bike is running");
       }
}
public class OverridingDemo3 {
public static void main(String[] args) {
       Bike bk = new Bike();
       bk.run(); // this calls the method present in child class
}
}

Example II:
class Animal1{
       public void whoAmI() {
             System.out.println("I am an Animal1");
       }
       
}
class Horse extends Animal1{
       public void whoAmI() {
             System.out.println("I am a horse");
       }
}
public class OverridingDemo {
public static void main(String[] args) {
       Animal1 a = new Animal1();//Animal1 reference and object
       Animal1 h = new Horse();//Animlal1 reference but Horse object
       a.whoAmI();//runs the method in Animal1 class
       h.whoAmI();//runs the method in Horse class
}
}
Example III:
package com.cerotid.oo.principles;
class Parent{}
class Child extends Parent{}
public class OverridingDemo3 {
public static void main(String[] args) {
       Parent p1 = new Parent();           //valid
       Parent p2 = new Child();            //valid
       Child c1 = new Child();             //valid
       //Child c2 = new Parent();           //not valid
//parent class reference variable is able to hold child class object but child class reference variable is not able to hold parent class object
}
}


Example IV:
class Parent{
         void m1() {
             System.out.println("parent m1()");//overridden method
       }
}
class Child extends Parent{
        void m1() {
             System.out.println("child m1()");//overriding method
       }
  void m2() {
         System.out.println("child m2()");
       }
}
  class OverridingDemo4{
             public static void main(String[] args) {
                    Parent p = new Child();
                    p.m1();
             //     p.m2() // not possible
                    //when you type cast from parent reference variable to child class object and it is possible to call m2() method
                  Child c = (Child) p;
                c.m2();
             }
       }
Output:
child m1()
child m2()
Note:I When I am calling p.m1(), at compile time, compiler is checking method in parent class, method is available and it is executed. At run time, child class object is created in the child class  and child class method is executed. 
II: when I am calling p.m2(), compile time compiler is checking method in parent class, method is not available and error message. Then we have to type cast parent class reference variable p to child class object and now we can call m2() without having error. 

Example VI: Parent class reference variable and child class object
package com.cerotid.oo.principles;
interface WebDriver{
       void get();// abstract method (ending with semicolon)
       void window();
}
class FirefoxDriver implements WebDriver{
       public void get() { }        //overriding method
       public void window() {    }     //overriding method
       void x() {   }          //direct method
       void y() {   }          //direct method
}
public class OverridingDemo5 {
public static void main(String[] args) {
       Parent p = new Child();// concept
       WebDriver driver = new FirefoxDriver();
       driver.get();// compile time: WebDriver            runtime: FirefoxDriver
       driver.window();//compile time: WebDriver            runtime: FirefoxDriver
       //driver.x();   //compile time : WebDriver            runtime: compilation error
       Need to type cast from (Parent class reference variable) driver to (Child class object) FirefoxDriver.
       FirefoxDriver f = (FirefoxDriver)driver;
       f.x();
       f.y();
}
}

Example VI: it is not possible to override the static methods in java because static methods are bonds with class
class Parent{
       static void m1() {
             System.out.println("parent m1()");//overridden method
       }
}
class Child extends Parent{
       static void m1() {
             System.out.println("child m1()");//overriding method
       }
}
class OverridingDemo4{
       public static void main(String[] args) {
             Parent p = new Child();
             p.m1();
       //     p.m2() // not possible
             //when you type cast from parent reference variable to child class object and it is possible to call m2() method
       }
}
Output: parent m1() because static methods are specific to class

No comments:

Post a Comment