天天看點

教妹學Java(三十六):Java 多态的好處

三妹開學了,學的計算機軟體程式設計。她學校離我家很近,坐公共汽車也就 10 站路的距離, 每逢周末她都會來找我,讓我輔導她學習 Java。作為一名擁有十餘年程式設計經驗的程式員,再加上父母給我們的這份血緣關系,我覺得義不容辭。

“二哥,今天我們要學習的内容是‘多态’,對吧?”看來三妹已經提前預習了我上次留給她的作業。

“是的,三妹。多态是 Java 中非常重要的一個概念。 ”我面帶着樸實無華的微笑回答着她,“多态來源于兩個希臘用語:poly(多)和 morphs(形态),是以多态(polymorphism)的意思是多種形态。”

“Java 中的多态有兩種形式:編譯時多态和運作時多态,可以通過方法重載和方法重寫來實作。重載靜态方法是編譯時多态,今天我們主要來談談運作時多态。”

----正兒八經的分割線,正文開始------------

運作時多态或者動态方法調用是指,在運作時而不是編譯時對重寫方法的調用過程。在這個過程中,通過父類的一個引用變量來調用重寫方法,具體調用的方法是通過引用指向的變量決定的。

如果一個父類的引用變量指向的是子類的對象,這被稱之為“向上轉型”。

代碼示例如下所示:

class A{}
class B extends A{}
public class UpcastingDemo {
    // 向上轉型
    A a = new B();
}      
7
對于向上轉型,我們既可以使用父類作為引用變量的類型,也可以使用接口作為引用變量的類型。
interface I {}
class A{}
class B extends A implements I {}
public class UpcastingByIntefaceDemo {
    I i = new B();
}      

關系是這樣的:

B is-a A

B is-a I

B is-a Object

因為 Object 類是 Java 中所有類的超類。

來看下面這個例子:

/**
 * @author 微信搜「沉默王二」,回複關鍵字 PDF
 */
class Father{
    void say() {
        System.out.println("老子說");
    }
}
public class Child extends Father {
    @Override
    void say() {
        System.out.println("孩子說");
    }
    public static void main(String[] args) {
        Father f = new Child();
        f.say();
    }
}      

在這個例子中,有兩個類,父類 Father 和子類 Child,子類重寫了父類的 say() 方法,我們可以通過父類的引用變量 f 來調用 say() 方法,但它指向的是子類對象,是以 Java 虛拟機在運作的時候會去調用子類的 say() 方法。來看一下程式的輸出結果:

孩子說

方法可以重寫(覆寫),但字段(成員變量)卻不可以。來看下面這個例子:

/**
 * @author 微信搜「沉默王二」,回複關鍵字 PDF
 */
class Car{
    int speedLimit = 60;
}
class Honda extends Car {
    int speedLimit = 90;
}
public class CanntOverrideMemberDataDemo {
    public static void main(String[] args) {
        Car car = new Honda();
        System.out.println(car.speedLimit);
    }
}      

程式輸出結果如下所示:

60

在上面的例子中,子類 Honda 和父類 Car 有一個相同名字的字段 speedLimit,我們可以通過父類的引用變量 car 去通路 speedLimit,雖然 car 指向的是子類對象,但由于字段是不能被覆寫的,是以 car.speedLimit 通路的仍然是父類的字段。

“三妹,Java 多态我們就學到這裡吧,它的用法我相信你一定全部掌握了。”我揉一揉犯困的雙眼,疲憊地給三妹說。

“好的,二哥,我這就去練習去。”三妹似乎意猶未盡,這種學習狀态真令我感到開心。