জাভা সুপার কিওয়ার্ড (Java super Keyword)

আমরা যদি সাব ক্লাস থেকে সুপার ক্লাসের কোন মেথড বা ভেরিয়েবল একসেস করতে চাই তাহলে আমরা এই কিওয়ার্ডটি ব্যবহার করি। কিন্তু আমরা জানি যে সাব ক্লাসে অটোমেটিক্যালি সুপার ক্লাসের সব প্রোপ্রার্টি চলে আসে তাহলে এর প্রয়োজনিয়তা নিয়ে প্রশ্ন হতে পারে।

আমরা আবার উপরের Cylinder ক্লাসটি আবার দেখি। এই ক্লাসটিতে আমরা নতুন আরেকটি মেথড লিখতে চাই।

      public double getVolume() {
            return getArea() * height;
        }

এই মেথডটি-তে getArea() * height এই স্ট্যাটমেন্টটি লক্ষ করি। এখানে getArea() এই মেথটি কল করা হয়েছে। আমাদের এই Cylinder ক্লাসটিতে getArea() মেথডটিকে আমরা Circle ক্লাস এর getArea()মেথড-কে অভারাইড করেছি। সুতরাং আমরা যখন এই Cylinder ক্লাস থেকে getArea() মেথডটি কল করবো তখন আসলে Cylinder ক্লাস এর মেথডটি কল হবে।

কিন্তু এক্ষেত্রে আমাদের একটি সমস্যা হচ্ছে যে – আমরা জানি সিলিন্ডারের আয়তন

V  = Pi * r^2 * h
    =  (Pi * r^2) * h
    =  Area of Circle * h 

সুতরাং Cylinder ক্লাসের ‌getArea() মেথডটি ব্যবহার করা যাচ্ছে না। কারণ সিলিন্ডারের ক্ষেত্রফল-

        A = (2 * Pi  * r * h)  +  (2 * Pi * r^2)

কিন্তু আমরা যদি Circle ক্লাস এর মেথডটি ব্যবহার করি তাহলে আমাদের সমস্যা সমাধান হয়ে যায়। এখন যদি আমরা সুপার ক্লাস(Circle) এর মেথডটি কল করে এই মেথডটি লিখতে চাই তাহলে –

     public double getVolume() {
            return super.getArea() * height;
     }

অর্থাৎ সাব ক্লাসে যদি মেথড অভাররাইড করা হয় এবং তারপরেও কোন কারণে যদি আমাদের সুপার ক্লাসের মেথড কে কল করার প্রয়োজন হয় তাহলে আমরা সুপার(super) কিওয়ার্ডটি ব্যবহার করি।

ইনহেরিটেন্স এর ক্ষেত্রে মনে রাখতে হবে –

জাভা মাল্টিপল ইনহেরিটেন্স সাপোর্ট করে না। এর মানে হচ্ছে আমার একটি ক্লাস শুধুমাত্র একটি ক্লাসকেই ইনহেরিট করতে পারে।

Usage of java super Keyword

  1. super can be used to refer immediate parent class instance variable.
  2. super can be used to invoke immediate parent class method.
  3. super() can be used to invoke immediate parent class constructor.

1) super is used to refer immediate parent class instance variable.

We can use super keyword to access the data member or field of parent class. It is used if parent class and child class have same fields.

class Animal{

String color=“white”;

}

class Dog extends Animal{

String color=“black”;

void printColor(){

System.out.println(color);//prints color of Dog class

System.out.println(super.color);//prints color of Animal class

}

}

class TestSuper1{

public static void main(String args[]){

Dog d=new Dog();

d.printColor();

}}

Test it Now

Output:

black
white

In the above example, Animal and Dog both classes have a common property color. If we print color property, it will print the color of current class by default. To access the parent property, we need to use super keyword.

2) super can be used to invoke parent class method

The super keyword can also be used to invoke parent class method. It should be used if subclass contains the same method as parent class. In other words, it is used if method is overridden.

class Animal{

void eat(){System.out.println(“eating…”);}

}

class Dog extends Animal{

void eat(){System.out.println(“eating bread…”);}

void bark(){System.out.println(“barking…”);}

void work(){

super.eat();

bark();

}

}

class TestSuper2{

public static void main(String args[]){

Dog d=new Dog();

d.work();

}}

Test it Now

Output:

eating...
barking...

In the above example Animal and Dog both classes have eat() method if we call eat() method from Dog class, it will call the eat() method of Dog class by default because priority is given to local.

To call the parent class method, we need to use super keyword.

3) super is used to invoke parent class constructor.

The super keyword can also be used to invoke the parent class constructor. Let’s see a simple example:

class Animal{

Animal(){System.out.println(“animal is created”);}

}

class Dog extends Animal{

Dog(){

super();

System.out.println(“dog is created”);

}

}

class TestSuper3{

public static void main(String args[]){

Dog d=new Dog();

}}

Test it Now

Output:

animal is created
dog is created

Note: super() is added in each class constructor automatically by compiler if there is no super() or this().

java super

As we know well that default constructor is provided by compiler automatically if there is no constructor. But, it also adds super() as the first statement.

Another example of super keyword where super() is provided by the compiler implicitly.

class Animal{

Animal(){System.out.println(“animal is created”);}

}

class Dog extends Animal{

Dog(){

System.out.println(“dog is created”);

}

}

class TestSuper4{

public static void main(String args[]){

Dog d=new Dog();

}}

Test it Now

Output:

animal is created
dog is created

super example: real use

Let’s see the real use of super keyword. Here, Emp class inherits Person class so all the properties of Person will be inherited to Emp by default. To initialize all the property, we are using parent class constructor from child class. In such way, we are reusing the parent class constructor.

class Person{

int id;

String name;

Person(int id,String name){

this.id=id;

this.name=name;

}

}

class Emp extends Person{

float salary;

Emp(int id,String name,float salary){

super(id,name);//reusing parent constructor

this.salary=salary;

}

void display(){System.out.println(id+” “+name+” “+salary);}

}

class TestSuper5{

public static void main(String[] args){

Emp e1=new Emp(1,“ankit”,45000f);

e1.display();

}}

Test it Now

Output:

1 ankit 45000
Advertisements

জাভা মেথড ওভাররাইডিং(Java Method Overriding)

Usage of Java Method Overriding

  • Method overriding is used to provide specific implementation of a method that is already provided by its super class.
  • Method overriding is used for runtime polymorphism

Rules for Java Method Overriding

  1. method must have same name as in the parent class
  2. method must have same parameter as in the parent class.
  3. must be IS-A relationship (inheritance).

Understanding the problem without method overriding

Let’s understand the problem that we may face in the program if we don’t use method overriding.

যদিও সাব-ক্লাস সুপার-ক্লাসের সব গুলো প্রোপ্রার্টি এবং মেথড ইনহেরিটর করে, তবে সাব-ক্লাসে সুপার ক্লাসের যে কোন প্রোপ্রার্টি বা মেথড কে অভাররাইড করা যায়।

একটি উদাহরণ দেখা যাক-

      public class Circle {
          double radius;
          String color;

          public Circle(double radius, String color) {
              this.radius = radius;
              this.color = color;
          }

          public Circle() {
              radius = 1.0;
              color = "RED";
          }

          public double getArea() {
              return radius * radius * Math.PI;
          }
      }

এই ক্লাসটিতে getArea() মেথড একটি বৃত্তের ক্ষেত্রফল রিটার্ন করে।

এখন আমরা এই ক্লাসটিকে এক্সটেন্ড(‌‌‌‌‌extends‌) করে নতুন আরেকটি ক্লাস লিখবো-

    public class Cylinder extends Circle {
        double height;

        public Cylinder() {
            this.height = 1.0;
        }

        public Cylinder(double radius, String color, double height) {
            super(radius, color);
            this.height = height;
        }

      @Override    
        public double getArea() {
            return 2 * Math.PI * radius * height + 2 * super.getArea();
        }
    }

এই ক্লাসটিতে Circle এর মেথডটি আমরা সাধারণ ভাবেই পেয়ে যাবো। Cylinder এর ক্ষেত্রফল নির্ধারণ করতে হলে getArea() কল করলেই হয়ে যাচ্ছে। কিন্তু আমরা জানি যে Circle এবং Cylinder এর ক্ষেত্রফল একভাবে নির্ধারণ করা যায় না। এক্ষেত্রে আমরা যদি Circle এর মেথডটি কে ব্যবহার করি তাহলে আমাদের ক্ষেত্রফলের মান ভুল আসবে। এই সমস্যা সমধাণ করার জন্যে আমরা আমাদের Cylinder ক্লাসটিতে getArea()মেথডটিকে পুনারায় লিখেছি।

এখানে লক্ষ্য রাখতে হবে যে, দুটি মেথড এর সিগনেচার, রিটার্ন-টাইপ এবং প্যারামিটার লিস্ট একই রকম হতে হবে।

এখন আমরা যদি Cylinder ক্লাস-এর getArea() মেথড কল করি, তাহলে অভারাইডেড মেথডটি কল হবে।

অ্যনোটেশান(Annotation) @Override

@Override এই অ্যনোটেশানটি জাভা 1.5 ভার্সনে প্রথম নিয়ে আসা হয়। কোন মেথডকে যদি আমরা অভাররাইড করি তাহলে সেই মেথড এর উপরে @Override দেয়া হয়। এটি কম্পাইলারকে ইনফর্ম করে যে, এই মেথটি সুপার ক্লাসের অভাররাইডেড মেথড।

তবে এটি অপশনাল হলেও অবশ্যই ভাল যদি ব্যবহার করা হয়।

Real example of Java Method Overriding

Consider a scenario, Bank is a class that provides functionality to get rate of interest. But, rate of interest varies according to banks. For example, SBI, ICICI and AXIS banks could provide 8%, 7% and 9% rate of interest.

Java method overriding example of bank

  1. class Bank{
  2. int getRateOfInterest(){return 0;}
  3. }
  4. class SBI extends Bank{
  5. int getRateOfInterest(){return 8;}
  6. }
  7. class ICICI extends Bank{
  8. int getRateOfInterest(){return 7;}
  9. }
  10. class AXIS extends Bank{
  11. int getRateOfInterest(){return 9;}
  12. }
  13. class Test2{
  14. public static void main(String args[]){
  15. SBI s=new SBI();
  16. ICICI i=new ICICI();
  17. AXIS a=new AXIS();
  18. System.out.println(“SBI Rate of Interest: “+s.getRateOfInterest());
  19. System.out.println(“ICICI Rate of Interest: “+i.getRateOfInterest());
  20. System.out.println(“AXIS Rate of Interest: “+a.getRateOfInterest());
  21. }
  22. }

Test it Now

Output:
SBI Rate of Interest: 8
ICICI Rate of Interest: 7
AXIS Rate of Interest: 9

Can we override static method?

No, static method cannot be overridden. It can be proved by runtime polymorphism, so we will learn it later.


Why we cannot override static method?

because static method is bound with class whereas instance method is bound with object. Static belongs to class area and instance belongs to heap area.


Can we override java main method?

No, because main is a static method.


Difference between method Overloading and Method Overriding in java

Click me for difference between method overloading and overriding


জাভা পলিমরফিজম ( Java Polymorphism )

এবার আমরা কথা বলবো পলিমরফিজম নিয়ে। শব্দটির মধ্যেই একটি বিশেষ গাম্ভীর্য আছে যা কিনা একটি সাধারণ কথোপকথনকে অনেক গুরুত্বর্পূণ করে তুলতে পারে। তবে এটি অবজেক্ট ওরিয়েন্টেড প্রোগ্রামিং এর একটি বহুল ব্যবহৃত কৌশল । এই শব্দটির সহজ মানে হচ্ছে যার একাধিক রূপ আছে অর্থাৎ বহুরূপিতা।

সহজ কথায় পলিমরফিজম হল এমন একটি টেকনিক বা পদ্ধতি যেখানে আমরা একটি ক্লাস, অ্যাবস্ট্রাক্ট ক্লাস বা ইন্টারফেসের অবজেক্ট ক্রিয়েট করি তার চাইল্ড ক্লাসের কনস্ট্রাক্টরের মাধ্যমে । অর্থাৎ আমরা একটি ক্লাসের অবজেক্ট ক্রিয়েট করবো অন্য একটি ক্লাসের কনস্ট্রাক্টর কল করে । সহজ ভাষায় এটিই হল পলিমরফিজম ।

মনে করা যাক, ‌‌ ‌

    public class Liquid {
        public void swirl(boolean clockwise) {
            // Implement the default swirling behavior for liquids
            System.out.println("Swirling Liquid");
        }
    }

এখন এর একটি অবজেক্ট তৈরি করতে চাইলে – আমাদের new অপারেটর ব্যবহার করে তা একটি ভেরিয়েবল এ রাখতে হবে।

        Liquid myFavoriteBeverage = new Liquid ();

এখানে myFavoriteBeverage হচ্ছে আমাদের ভেরিয়েবল যা Liquid অবজেক্ট এর রেফারেন্স। আমরা এখন পর্যন্ত যা যা শিখেছি সে অনুযায়ী এই স্টেন্টমেন্টটি যথার্থ। তবে আমরা এর আগের অধ্যায়ে Is-A সম্পর্কে জেনে এসেছি।

আমাদের জাভা প্রোগ্রামিং পলিমরফিজম সাপোর্ট করায় আমরা myFavoriteBeverage এই রেফারেন্সের যায়গায় Is-A সম্পর্কিত যে কোন টাইপ রাখতে পারি। যেমন – ‌ ‌


    Liquid myFavoriteBeverage = new Coffee();
    Liquid myFavoriteBeverage = new Milk();

এখানে Coffee এবং Milk হচ্ছেLiquidএর সাব- ক্লাস বা টাইপ এবং Liquid এদের সুপার ক্লাস বা টাইপ।

পলিমরফিজম নিয়ে আরও একটু আশ্চর্য হতে চাইলে আমরা এখন একটি বিষয় জানবো যা দিয়ে আমরা কোন একটি অবজেক্ট এর কোন মেথড কল করবো তবে তা কোন ক্লাসের অবজেক্ট সেটি না জেনেই। আরেকটু পরিষ্কার করে বলি, আমরা যখন সুপার ক্লাসের এর রেফারেন্স ধরে কোন এর মেথড কল করবো তখন কিন্তু আমরা জানি না যে এটি আসলে কোন অবজেক্ট এর মেথড। যেমন- ‌ ‌


    Liquid myFavoriteBeverage = // ….

এখানে আমাদের myFavoriteBeverage এই রেফারেন্স এ LiquidCoffeeMilk এর যেকোন একটির অবজেক্ট হতে পারে। উদাহরণ –

    public class Coffee extends Liquid {
        @Override
        public void swirl(boolean clockwise) {
            System.out.println("Swirling Coffee");
        }
    }

    public class Milk extends Liquid{
        @Override
        public void swirl(boolean clockwise) {
            System.out.println("Swirling Milk");
        }
    } 

    public class CoffeeCup {
        private Liquid innerLiquid;

        void addLiquid(Liquid liq) {
            innerLiquid = liq;
            // Swirl counterclockwise
            innerLiquid.swirl(false);
        }
    }

আমরা এখানে একটি CoffeeCup ক্লাস লিখেছি যার মাঝে addLiquid() নামে একটি মেথড আছে যা কিনা একটি Liquid টাইপ parameter নেয়, এবং সেই Liquid এর swirl() মেথড-কে কল করে।

কিন্তু আমরা আমাদের সত্যিকারের জগতে একটি কফি-কাপ এ শুধুমাত্র কফি-ই এড করতে পারি তা নয়, আমরা চাইলে যে কোন ধরণের লিকুইড এড করতে পারি, সেটি মিল্ক ও হতে পারে। তাহলে এই addLiquid মেথড তো শুধুমাত্র Liquid টাইপ parameter নেয়, তাহলে আমাদের সত্যিকারের জগতের সাথে এই প্রোগ্রামিং মডেল এর সাদৃশ্য থাকলো কোথায় ?

তবে মজার ব্যপার এখানেই, আমাদের এই CoffeeCup ক্লাসটি পলিমরফিজমের ম্যজিক ব্যাবহার করে সত্যিকার অর্থেই আমাদের সত্যিকারের জগতের CoffeeCup এর মতোই কাজ করে। ‌


    public class MainApp {
        public static void main(String[] args) {
            // First you need a coffee cup
            CoffeeCup myCup = new CoffeeCup();

            // Next you need various kinds of liquid
            Liquid genericLiquid = new Liquid();
            Coffee coffee = new Coffee();
            Milk milk = new Milk();

            // Now you can add the different liquids to the cup
            myCup.addLiquid(genericLiquid);
            myCup.addLiquid(coffee);
            myCup.addLiquid(milk);
        }
    }

উপরের কোড গুলোতে দেখা যাচ্ছে যে আমরা একটি CoffeeCup এর একটি অবজেক্ট তৈরি করে সেটি তে বিভিন্ন রকম Liquid এড করতে পারছি।

আরেকটু লক্ষ্য করি,

    void addLiquid(Liquid liq) {
            innerLiquid = liq;
            // Swirl counterclockwise
            innerLiquid.swirl(false);
      }

এই মেথডটিতে innerLiquid.swirl(false) যখন কল করি তখন কিন্তু আমরা জানি না যে এই innerLiquid আসলে কোন অবজেক্ট এর রেফারেন্স। এটি লিকুইড বা এর যে কোন সাব-টাইপ হতে পারে।

কিছু প্রয়োজনীয় তথ্য-

১. একটি সাব ক্লাস এর অবজেক্টকে আমরা এর সুপার ক্লাসের রেফারেন্স এ এসাইন করতে পারি। ২. সাব ক্লাসের অবজেক্টকে সুপার ক্লাসের রেফারেন্স-এ এসাইন করলে, মেথড কল করার সময় শুধু মাত্র সুপার ক্লাসের মেথড গুলোকেই কল করতে পারি। ৩. তবে সাব ক্লাস যদি সুপার ক্লাসের মেথড অভাররাইড করে, তাহলে যদিও আমরা সুপার ক্লাস এর রেফারেন্স ধরে মেথড কল করছি, কিন্তু রানটাইম-এ সাব ক্লাসের মেথডটি কল হবে। মনে রাখতে হবে এটি শুধুমাত্র মেথড অভাররাইড করা হলেই সত্য হবে।

আপ-কাস্টিং(Upcasting ) এবং ডাউনকাস্টিং (Downcasting)

        Liquid liquid = new Coffee ();

এখানে সাব ক্লাসের অবজেক্টকে সুপার ক্লাসের রেফারেন্স এ এসাইন করা হয়ছে। একে বলা হয় আপ-কাস্টিং। এই কাস্টিং সবসময় সেইফ ধরা হয় কারণ আপকাস্টং এর ক্ষেত্রে সাব ক্লাস সবসময়ই সুপার ক্লাসের সবকিছু ইনহেরিট করে এবং কম্পাইলার কম্পাইল করার সময়-ই এ কাস্টিং করা সম্ভব কিনা তা চেক করে থাকে।

        Liquid liquid = new String();

উপরের স্টেটমেন্টটি কম্পাইলার কম্পাইল করবে না, কারণ String মোটেই Liquid ক্লাসের সাব ক্লাস নয়। এক্ষেত্রে কম্পাইলার incompatible types ইরর দেখাবে।

হোমেজিনিয়াস কালেকশন ( Homogeneous Collection ):

হোমোজিনিয়াস কালেকশন হল একই ক্লাসের কিছু সংখ্যক অবজেক্টের কালেকশন । একটি উদাহরন দিয়ে বিষয়টি একটু সুরাহা করা যাকঃ

interface Animal {

    public abstract void name(String animalName);
}

class Cow implements Animal {

    private String animalName;

    public void work(String animalWork) {
        System.out.println("Work of " + this.animalName + " is " + animalWork);
    }

    @Override
    public void name(String animalName) {
        this.animalName = animalName;
        System.out.println("Name of the animal is: " + this.animalName);
    }
}

public class Main {

    public static void main(String[] args) {

        Animal[] collection1 = new Cow[3];
        collection1[0] = new Cow();
        collection1[1] = new Cow();
        collection1[2] = new Cow();

        Cow[] collection2 = new Cow[3];
        collection2[0] = new Cow();
        collection2[1] = new Cow();
        collection2[2] = new Cow();
    }
}

লক্ষ করুন । এখানে Cow ক্লাসটি Animal ইন্টারফেসের চাইল্ড । এবং Main ক্লাসের main মেথড এর মাঝে ২ টি অবজেক্টের অ্যারে ডিক্লেয়ার করা হয়েছে । একটি Animal ক্লাসের অবজেক্টের অ্যারে যেটির সবগুলা অবজেক্ট Cow ক্লাসের কনস্ট্রাক্টর দিয়ে ইন্সট্যানশিয়েট করা হয়েছে । এখানে পলিমরফিজম স্পষ্ট । এবং অন্যটি অবজেক্ট অ্যারেটি চীরাচরিত অবজেক্ট অ্যারে । এই দুইি অ্যারেই হল হোমোজিনিয়াস কালেকশনের উদাহরন । বোঝা যায়নি ? ওকে, এখানে collection1 অ্যারেটির প্রতিটি অবজেক্টই Cow ক্লাসের কনস্ট্রাক্টর দিয়ে ইন্সট্যানশিয়েট করা হয়েছে । তার মানে collection1 এর মাঝে সবগুলা অবজেক্টই একই ধরনের । যেহেতু এই অ্যারেটির সবগুলা এলিমেন্ট একই ধরনের/ক্লাসের অবজেক্ট সুতরাং এটিকে বলা হবে হোমোজিনিয়াস কালেকশন । একই কথা collection2 এর ক্ষেত্রেও প্রোযোজ্য ।

হেটারোজিনিয়াস কালেকশন ( Heterogeneous Collection ):

ভিন্নধর্মী অবজেক্টের কালেকশনকেই বলা হয় হেটারোজিনিয়াস কালেকশন । হেটারোজিনিয়াস কালেকশন বুঝতে হলে আমাদের একটি উদাহরন দেখে নেওয়া উত্তমঃ

class Animal {

    String animalName ;
    public Animal(String animalName){
        this.animalName = animalName;
    }
    public void name(){
        System.out.println("Animal name is: "+this.animalName);
    }
}

class Cow extends Animal {

    public Cow(String animalName) {
        super(animalName);
    }

    public void work(String animalWork) {
        System.out.println("Work of " + this.animalName + " is " + animalWork);
    }
}

class Dog extends Animal {

    public Dog(String animalName) {
        super(animalName);
    }

    public void work(String animalWork) {
        System.out.println("Work of " + this.animalName + " is " + animalWork);
    }
}

class Cat extends Animal {

    public Cat(String animalName) {
        super(animalName);
    }

    public void work(String animalWork) {
        System.out.println("Work of " + this.animalName + " is " + animalWork);
    }
}

public class Main {

    public static void main(String[] args) {

        Animal[] animals = new Animal[4];
        animals[0] = new Animal("Dolphin");
        animals[1] = new Cow("Big Cow");
        animals[2] = new Dog("Red Dog");
        animals[3] = new Cat("White Cat");
    }
}

খুব ভালোভাবে লক্ষ করুন । আমরা Animal ক্লাসের অবজেক্টের একটু অ্যারে ডিক্লেয়ার করেছি যার সাইজ ৪ । কিন্তু ইন্সট্যানশিয়েট করার সমস আমরা পলিমরফিজম মেকানিজম ব্যাবহার করে এর চাইল্ড ক্লাসের ভিন্ন ভিন্ন কনস্ট্রাক্টর দিয়ে ইন্সট্যানশিয়েট করেছি । অর্থাৎ animals অ্যারেটির প্রতিটি অবজেক্টই আলাদা আলাদা কনস্ট্রাক্ট দিয়ে ইন্সট্যানশিয়েট করা এবং তাদের বিহ্যাভিয়েরাল পার্থ্য আছে । এধরনের কালেকশনকে বলা হয় হেটারোজিনিয়াস কালেকশন ।

এবার একটু ভিন্ন পন্থায় এগোন যাক । মেইন ক্লাসটিকে আমরা একটু মডিফাই করবো । বাকী সবই ঠিক থাকবে আগের মত ।

public class Main {

    public static void main(String[] args) {

        Animal animal = new Cat("Cute Cat");
        animal.name();
        //animal.work("Some Work");//Not possible
        Cat cat = new Cat("Preety Cat");
        cat.name();
        cat.work("It plays");
    }
}

খেয়াল করে দেখুন আমরা Animal এবং Cat এর অবজেক্ট ক্রিয়েট করার সময় কনস্ট্রাক্টর ব্যাবহার করেছি Catএর কিন্তু Animal এর অবজেক্ট থেকে আমরা work মেথডটি কোন ভাবেই কল করতে পারছি না বা পারবো না কিন্তু Cat এর অবজেক্ট থেকে ঠিকই পারছি । কারনটা কি ? কারন হল Animal ক্লাসের মাঝে ঠিক যে যে মেথড আছে সেগুলাকেই আমরা অ্যাক্সেস করতে পারব তবে Cat এর ইমপ্লিমেন্টেশন দিয়ে । Animal এর মাঝে নেই কিন্তু Cat ক্লাসে বাড়তি আছে এমন কোন মেথডকে আমরা অ্যাক্সেস করতে পারবো না । এমনকি Animalক্লাসের অবজেক্টে Cat ক্লাসের work মেথডের কোন রেফারেন্সই ক্রিয়েট হবেনা ।

তাহলে এটা করি কেন আমরা ? এটা করার পেছনে বেশ কিছু কারন থাকতে পারে । প্রথমত আমরা প্যারেন্ট ক্লাস এবং চাইল্ড ক্লাসের ইমপ্লিমেন্টশন নিয়ে কাজ করতে চাইলে পলিমরফিজমের এই সুবিধাটি নেওয়া হয় । অন্য কারনটি হল মেমোরি কনজাম্পশন । ভেবে দেখুন যদি Animal ক্লাসে ৩ টি মেথড থাকে যেগুলার জন্য আপনি Cat ক্লাসের ইমপ্লিমেন্টেশন ব্যাবহার করতে চান , কিন্তু Cat ক্লাসের মাঝে ১৫ টির মত মেথড আছে এবং অনেক অ্যাট্রিবিউট । আপনি যদি Cat এর অবজেক্ট ক্রিয়েট করেন তবে মেমোরি থেকে প্রচুর স্পেস কনজিউম করবে উক্ত অবজেক্ট । অন্যদিকে আপনি যদি Animal এর অবজেক্ট ক্রিয়েট করেন Cat এর কনস্ট্রাক্টর ব্যাবহার করে তাহলে Cat ক্লাসের ইমপ্লিমেন্টেশন ব্যাবহার করতে পারছেন এবং মেমোরি থেকে খুব কম মেমোরি কনজিউম করছে ( Animal মেথডগুলার জন্য প্রয়োজনীয় মোমোরি মাত্র ) । কোনটি বেশি সুবিধাজনক ? এছাড়া আরো কারন আছে । পরবর্তীতে সেগুলা নিয়েও আলোচনা করা হবে ।

Runtime Polymorphism in Java

Runtime polymorphism or Dynamic Method Dispatch is a process in which a call to an overridden method is resolved at runtime rather than compile-time.

In this process, an overridden method is called through the reference variable of a superclass. The determination of the method to be called is based on the object being referred to by the reference variable.

Let’s first understand the upcasting before Runtime Polymorphism.

Upcasting

When reference variable of Parent class refers to the object of Child class, it is known as upcasting. For example:

Upcasting in java

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

Example of Java Runtime Polymorphism

In this example, we are creating two classes Bike and Splendar. Splendar class extends Bike class and overrides its run() method. We are calling the run method by the reference variable of Parent class. Since it refers to the subclass object and subclass method overrides the Parent class method, subclass method is invoked at runtime.

Since method invocation is determined by the JVM not compiler, it is known as runtime polymorphism.

class Bike{

void run(){System.out.println(“running”);}

}

class Splender extends Bike{

void run(){System.out.println(“running safely with 60km”);}

 

public static void main(String args[]){

Bike b = new Splender();//upcasting

b.run();

}

}

Test it Now

Output:running safely with 60km.

Java Runtime Polymorphism Example: Bank

Consider a scenario, Bank is a class that provides method to get the rate of interest. But, rate of interest may differ according to banks. For example, SBI, ICICI and AXIS banks are providing 8.4%, 7.3% and 9.7% rate of interest.

Java Runtime Polymorphism example of bank

Note: This example is also given in method overriding but there was no upcasting.

class Bank{

float getRateOfInterest(){return 0;}

}

class SBI extends Bank{

float getRateOfInterest(){return 8.4f;}

}

class ICICI extends Bank{

float getRateOfInterest(){return 7.3f;}

}

class AXIS extends Bank{

float getRateOfInterest(){return 9.7f;}

}

class TestPolymorphism{

public static void main(String args[]){

Bank b;

b=new SBI();

System.out.println(“SBI Rate of Interest: “+b.getRateOfInterest());

b=new ICICI();

System.out.println(“ICICI Rate of Interest: “+b.getRateOfInterest());

b=new AXIS();

System.out.println(“AXIS Rate of Interest: “+b.getRateOfInterest());

}

}

Test it Now

Output:

SBI Rate of Interest: 8.4
ICICI Rate of Interest: 7.3
AXIS Rate of Interest: 9.7

Java Runtime Polymorphism Example: Shape

class Shape{

void draw(){System.out.println(“drawing…”);}

}

class Rectangle extends Shape{

void draw(){System.out.println(“drawing rectangle…”);}

}

class Circle extends Shape{

void draw(){System.out.println(“drawing circle…”);}

}

class Triangle extends Shape{

void draw(){System.out.println(“drawing triangle…”);}

}

class TestPolymorphism2{

public static void main(String args[]){

Shape s;

s=new Rectangle();

s.draw();

s=new Circle();

s.draw();

s=new Triangle();

s.draw();

}

}

Test it Now

Output:

drawing rectangle...
drawing circle...
drawing triangle...

Java Runtime Polymorphism Example: Animal

class Animal{

void eat(){System.out.println(“eating…”);}

}

class Dog extends Animal{

void eat(){System.out.println(“eating bread…”);}

}

class Cat extends Animal{

void eat(){System.out.println(“eating rat…”);}

}

class Lion extends Animal{

void eat(){System.out.println(“eating meat…”);}

}

class TestPolymorphism3{

public static void main(String[] args){

Animal a;

a=new Dog();

a.eat();

a=new Cat();

a.eat();

a=new Lion();

a.eat();

}}

Test it Now

Output:

eating bread...
eating rat...
eating meat...

Java Runtime Polymorphism with Data Member

Method is overridden not the datamembers, so runtime polymorphism can’t be achieved by data members.
In the example given below, both the classes have a datamember speedlimit, we are accessing the datamember by the reference variable of Parent class which refers to the subclass object. Since we are accessing the datamember which is not overridden, hence it will access the datamember of Parent class always.

Rule: Runtime polymorphism can’t be achieved by data members.

class Bike{

int speedlimit=90;

}

class Honda3 extends Bike{

int speedlimit=150;

 

public static void main(String args[]){

Bike obj=new Honda3();

System.out.println(obj.speedlimit);//90

}

Test it Now

Output:

90

Java Runtime Polymorphism with Multilevel Inheritance

Let’s see the simple example of Runtime Polymorphism with multilevel inheritance.

class Animal{

void eat(){System.out.println(“eating”);}

}

class Dog extends Animal{

void eat(){System.out.println(“eating fruits”);}

}

class BabyDog extends Dog{

void eat(){System.out.println(“drinking milk”);}

public static void main(String args[]){

Animal a1,a2,a3;

a1=new Animal();

a2=new Dog();

a3=new BabyDog();

a1.eat();

a2.eat();

a3.eat();

}

}

Test it Now

Output:

eating
eating fruits
drinking Milk

Try for Output

class Animal{

void eat(){System.out.println(“animal is eating…”);}

}

class Dog extends Animal{

void eat(){System.out.println(“dog is eating…”);}

}

class BabyDog1 extends Dog{

public static void main(String args[]){

Animal a=new BabyDog1();

a.eat();

}}

Test it Now

Output:

Dog is eating

Since, BabyDog is not overriding the eat() method, so eat() method of Dog class is invoked.

জাভা ইনহেরিটেন্স ( Java Inheritance )

ইনহেরিটেন্স নিয়ে কথা বলতে হলে এর সাথে আরেকটি বিষয় চলে আসে সেটি হলো অবজেক্ট কম্পোজিশান। এটি মোটামুটিভাবে একটু কঠিন অন্যান্য টপিক থেকে। তাই এই টপিকটি পড়ার সময় একটু ধৈর্য্য নিয়ে পড়তে হবে।

তো শুরু করার যাক-

প্রথমেই আমরা কথা বলবো Is – A এবং Has – A নিয়ে।

যেহেতু আমরা জাভা প্রোগ্রামিং শুরু করেছি, তো আমরা যতই এর ভেতরে প্রবেশ করতে শুরু করবো, ততই বুঝতে শুরু করবো যে ক্লাস আসলে একটা স্ট্যান্ড এলোন কম্পোনেন্ট নয়, বরং এটি অন্যান্য ক্লাসের উপর নির্ভর করে। অর্থাৎ ক্লাস গুলো একটি রিলেশন মেইনটেইন করে চলে। এই রিলেশন গুলো সাধারণত দুই ধরণের হয়- Is – A এবং Has – A।

আমাদের বাস্তব জগৎ থেকে একটা এনালজি দেয়া যাক । যেমন একটি বিড়াল, কিংবা কার অথবা বাস। বিড়াল হচ্ছে একটি প্রাণি। কার এর থাকে চাকা এবং ইঞ্জিন। বাস এরও থাকে চাকা এব ইঞ্জিন। আবার কার এবং বাস দুটিই ভেহিকল বা যান।

এখানে যে উদাহরণ গুলো দেয়া হয়েছে এর সবগুলো মূলত Is – A অথবা Has – A রিলেশনশিপ মেইনটেইন করে । যেমন –

A cat is an Animal (বিড়াল একটি প্রাণি ।) A car has wheels ( কার এর চাকা আছে ।)
A car has an engine ( কার এর একটি ইঞ্জিন আছে ।)

তো ব্যপারটি একদম সহজ। ঠিক এই ব্যপারটিকে আমরা আমাদের অবজেক্ট ওরিয়েন্টেট কনসেপ্ট এর মাধ্যমে বলতে পারি। যখন কোন অবজেক্ট এর মাঝে Is – A এই সম্পর্কটি দেখবো তাকে বলবো ইনহেরিটেন্স। আবার যখন কোন অবজেক্ট এর মাঝে Has – A এই সম্পর্কটি দেখবো তখন সেই ব্যপারটিকে বলবো অবজেক্ট কম্পোজিশান।

ইনহেরিটেন্স মূলত একটি ট্রি-রিলেশানশিপ। অর্থাৎ এটি একটি অবজেক্ট থেকে ইনহেরিট করে আসে।

আর যখন আমরা অনেকগুলো অবজেক্ট নিয়ে আরেকটি অবজেক্ট তৈরি করবো তখন সেই নতুন অবজেক্ট হলো মেইড-আপ বা নতুন তৈরি করা অবজেক্ট এই ঘটনাটি হলো কম্পোজিশান।

এর সবই আসলে একটি কনসেপ্ট এবং আইডিয়া থেকে এসেছে, সেটি হলো কোড রিইউজ করা এবং সিম্পল করা। যেমন দুটি অবজেক্ট এর কোড এর কিছু অংশ যদি কমন থাকে তাহলে আমরা সেই অংশটিকে দুইটি ক্লাসের মধ্যে পুনরায় না লিখে বরং তাকে ব্যবহার করতে পারি।

ধরা যাক, আমরা দুটি অবজেক্ট তৈরি করতে চাই- Animal এবং Cat

আমরা জানি যে সব Animal খায়, ঘুমায়। সুতরাং আমরা এই ক্লাসে এই দুটি বৈশিষ্ট্য আমরা এই ক্লাসে লিখতে পারি। আবার যেহেতু আমরা জানি যে Cat হচ্ছে একটি Animal। সুতরাং আমরা যদি এমন ভাবে কোড লিখতে পারি, যাতে করে এই Cat ক্লাসের মধ্যে নতুন করে আর সেই দু্টি বৈশিষ্ট্যের কোড আর লিখতে হচ্ছে না, বরং আমর এই Animal ক্লাসটিকে রিইউজ করলাম, তাহলে যে ঘটনাটি ঘটবে তাকেই মূলত ইনহেরিটেন্স বলা হয়।

এইভাবে আমরা আরও অন্যান্য Animal যেমন, Dog, Cow ইত্যাদি ক্লাস লিখতে পারি।

কম্পোজিশান তুলনামূলক ভাবে একটু সহজ।

Why use inheritance in java

  • For Method Overriding (so runtime polymorphism can be achieved).
  • For Code Reusability.

Syntax of Java Inheritance

  1. class Subclass-name extends Superclass-name
  2. {
  3.    //methods and fields
  4. }

The extends keyword indicates that you are making a new class that derives from an existing class. The meaning of “extends” is to increase the functionality.

In the terminology of Java, a class which is inherited is called parent or super class and the new class is called child or subclass.

Types of inheritance in java

On the basis of class, there can be three types of inheritance in java: single, multilevel and hierarchical.

In java programming, multiple and hybrid inheritance is supported through interface only. We will learn about interfaces later.

types of inheritance in java

Note: Multiple inheritance is not supported in java through class.

When a class extends multiple classes i.e. known as multiple inheritance. For Example:

Why multiple inheritance is not supported in java?

To reduce the complexity and simplify the language, multiple inheritance is not supported in java.

Consider a scenario where A, B and C are three classes. The C class inherits A and B classes. If A and B classes have same method and you call it from child class object, there will be ambiguity to call method of A or B class.

Since compile time errors are better than runtime errors, java renders compile time error if you inherit 2 classes. So whether you have same method or different, there will be compile time error now.

class A{

void msg(){System.out.println(“Hello”);}

}

class B{

void msg(){System.out.println(“Welcome”);}

}

class C extends A,B{//suppose if it were

 

Public Static void main(String args[]){

C obj=new C();

obj.msg();//Now which msg() method would be invoked?

}

}

Test it Now

 Compile Time Error

যেমন আমরা একটি Car তৈরি করতে চাই। Car তৈরি করতে হলে আমাদের লাগবে Wheel এবং Engine. সুতরাং আমরা Wheel এবং Engine এই দুটি ক্লাসকে নিয়ে নতুন আরেকটি ক্লাস লিখবো।

এবার তাহলে একটি উদাহরণ দেখা যাক।

public class Bicycle {

        // the Bicycle class has three fields
        public int cadence;
        public int gear;
        public int speed;

        // the Bicycle class has one constructor
        public Bicycle(int startCadence, int startSpeed, int startGear) {
            gear = startGear;
            cadence = startCadence;
            speed = startSpeed;
        }

        // the Bicycle class has four methods
        public void setCadence(int newValue) {
            cadence = newValue;
        }

        public void setGear(int newValue) {
            gear = newValue;
        }

        public void applyBrake(int decrement) {
            speed -= decrement;
        }

        public void speedUp(int increment) {
            speed += increment;
        }   
    }

উপরের Bicycle ক্লাসটিতে তিনটি ফিল্ড এবং চারটি মেথড আছে। এবার এই Bicycle থেকে আমরা এর একটি সাব-ক্লাস লিখবো

public class MountainBike extends Bicycle {

        // the MountainBike subclass adds one field
        public int seatHeight;

        // the MountainBike subclass has one constructor
        public MountainBike(int startHeight,
                            int startCadence,
                            int startSpeed,
                            int startGear) {
            super(startCadence, startSpeed, startGear);
            seatHeight = startHeight;
        }   

        // the MountainBike subclass adds one method
        public void setHeight(int newValue) {
            seatHeight = newValue;
        }   
    }

এই MountainBike ক্লাসটি উপরে Bicycle এর সব ফিল্ড এবং মেথড গুলো ইনহেরিট করে এবং এতে নতুন করে শুধু একটি ফিল্ড এবং একটি মেথড লেখা হয়েছে। তাহলে আমাদের MountainBike ক্লাসটিতে Bicycle ক্লাসটির সব প্রোপ্রাটি এবং মেথড অটোম্যাটিক্যালি পেয়ে গেলো।

এখানে এ Bicycle হচ্ছে সুপার ক্লাস(Super Class) এবং MountainBike হচ্ছে সাব-ক্লাস(Sub Class) । অর্থাৎ যে ক্লাস থেকে ইনহেরিট করা হয় তাকে বলা হয় সুপার ক্লাস এবং যে ক্লাস সাব ক্লাস থেকে ইনহেরিট করে

Single Inheritance Example

class Animal{

void eat(){System.out.println(“eating…”);}

}

class Dog extends Animal{

void bark(){System.out.println(“barking…”);}

}

class TestInheritance{

public static void main(String args[]){

Dog d=new Dog();

d.bark();

d.eat();

}}

Output:

barking...
eating..

Multilevel Inheritance Example

class Animal{

void eat(){System.out.println(“eating…”);}

}

class Dog extends Animal{

void bark(){System.out.println(“barking…”);}

}

class BabyDog extends Dog{

void weep(){System.out.println(“weeping…”);}

}

class TestInheritance2{

public static void main(String args[]){

BabyDog d=new BabyDog();

d.weep();

d.bark();

d.eat();

}}

Output:

weeping...
barking...
eating...

Hierarchical Inheritance Example

class Animal{

void eat(){System.out.println(“eating…”);}

}

class Dog extends Animal{

void bark(){System.out.println(“barking…”);}

}

class Cat extends Animal{

void meow(){System.out.println(“meowing…”);}

}

class TestInheritance3{

public static void main(String args[]){

Cat c=new Cat();

c.meow();

c.eat();

//c.bark();//C.T.Error

}}

Output:

meowing...
eating...

JVM মেমোরি স্ট্রাকচার (JVM Memory Structure)

JVM (Java Virtual Machine):

JVM (Java Virtual Machine) একটি abstract মেশিন। এটি একটি স্পেসিফিকেশন যা রানটাইম এনভায়রনমেন্ট সরবরাহ করে যার মধ্যে Java বাইট কোডে চালানো যায় ।

JVMs অনেক হার্ডওয়্যার এবং সফ্টওয়্যারের জন্য  available (i.e. JVM প্লাটর্ফম নির্ভরশীল)।

JVM কি ঃ

Continue reading JVM মেমোরি স্ট্রাকচার (JVM Memory Structure)