Java多型


Java中的多型是一個概念,通過它我們可以通過不同的方式執行單個動作(方法)。 多型性派生自2個希臘詞:「poly」和「morphs」。 詞語「poly」意為許多,「morphs」意為形式。 所以多型表示為多種形式。

在Java中有兩種型別的多型性:編譯時多型性和執行時多型性。 我們可以通過方法過載和方法覆蓋在java中執行多型性。

如果在Java中過載靜態方法,它就是編譯時多型性的例子。 這裡,我們將關注Java中的執行時多型性。

1. Java執行時多型性

執行時多型性或動態方法分派是一個過程,它對重寫方法的呼叫在執行時體現而不是編譯時。

在此過程中,通過超類的參照變數呼叫重寫的方法。 要呼叫的方法基於參照的物件。

了解執行時多型性之前,讓我們先來向上轉換。

向上轉換

當父類別的參照變數參照子類的物件時,稱為向上轉換。 例如:

class A{}  
class B extends A{}  
A a=new B();  //向上轉換...

Java執行時多型性範例1

在這個例子中,我們建立兩個類:BikeSplendarSplendar類擴充套件Bike類並覆蓋其run()方法。通過父類別(Bike)的參照變數呼叫run方法。 因為它參照子類物件,並且子類方法覆蓋父類別方法,子類方法在執行時被呼叫。

因為方法呼叫是由JVM不是編譯器決定的,所以它被稱為執行時多型性。
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();
    }
}

執行上面程式碼得到以下結果 -

running safely with 60km.

Java執行時多型性範例2:Bank

考慮一種情況,Bank類是一個提供獲得利率的方法的類。 但是,利率可能因銀行而異。 例如,SBIICICIAXIS銀行分別提供8.4%7.3%9.7%的利率。

注意:此範例也在方法覆蓋中給出,但沒有向上轉換。

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());
    }
}

上面程式碼執行結果如下 -

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

Java執行時多型性範例3: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();
    }
}

上面程式碼執行結果如下 -

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

Java執行時多型性範例4: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();
    }
}

上面程式碼執行結果如下 -

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

Java執行時多型性與資料成員

上面範例中,都是有關方法被覆蓋而不是資料成員,因此執行時多型性不能由資料成員實現。
在下面給出的例子中,這兩個類都有一個資料成員:speedlimit,通過參照子類物件的父類別的參照變數來存取資料成員。 由於我們存取的資料成員沒有被重寫,因此它將存取父類別的資料成員。

規則: 執行時多型性不能由資料成員實現。

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 
    }
}

上面程式碼執行結果如下 -

90

Java執行時多型性與多級繼承

下面讓我們來看看一個帶有多級繼承的執行時多型性的簡單例子。

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();
    }
}

上面程式碼執行結果如下 -

eating
eating fruits
drinking Milk

嘗試下面一段程式碼的輸出:

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();
    }
}

執行上述程式碼,結果如下:

Dog is eating

因為,BabyDog不會覆蓋eat()方法,所以這裡是Dog類的eat()方法被呼叫。