java——多型
一. 多型
面向物件程式設計有三大特性:封裝、繼承、多型。
封裝隱藏了類的內部實現機制,可以在不影響使用的情況下改變類的內部結構,同時也保護了資料。對外界而已它的內部細節是隱藏的,暴露給外界的只是它的訪問方法。
繼承是為了重用父類程式碼。兩個類若存在IS-A的關係就可以使用繼承,同時繼承也為實現多型做了鋪墊。
所謂多型就是指程式中定義的引用變數所指向的具體型別和通過該引用變數發出的方法呼叫在程式設計時並不確定,而是在程式執行期間才確定,即一個引用變數倒底會指向哪個類的例項物件,該引用變數發出的方法呼叫到底是哪個類中實現的方法,必須在由程式執行期間才能決定。因為在程式執行時才確定具體的類,這樣,不用修改源程式程式碼,就可以讓引用變數繫結到各種不同的類實現上,從而導致該引用呼叫的具體方法隨之改變,即不修改程式程式碼就可以改變程式執行時所繫結的具體程式碼,讓程式可以選擇多個執行狀態,這就是多型性。
1. 多型的優點
- 1. 消除型別之間的耦合關係
- 2. 可替換性
- 3. 可擴充性
- 4. 介面性
- 5. 靈活性
- 6. 簡化性
2. 多型存在的三個必要條件
- 繼承
- 重寫
- 父類引用指向子類物件
當使用多型方式呼叫方法時,首先檢查父類中是否有該方法,如果沒有,則編譯錯誤;如果有,再去呼叫子類的同名方法。
指向子類的父類引用由於向上轉型了,它只能訪問父類中擁有的方法和屬性,而對於子類中存在而父類中不存在的方法,該引用是不能使用的,儘管是過載該方法。若子類重寫了父類中的某些方法,在呼叫該些方法的時候,必定是使用子類中定義的這些方法(動態連線、動態呼叫)。
對於面向物件而已,多型分為編譯時多型和執行時多型。其中編輯時多型是靜態的,主要是指方法的過載,它是根據引數列表的不同來區分不同的函式,通過編輯之後會變成兩個不同的函式,在執行時談不上多型。而執行時多型是動態的,它是通過動態繫結來實現的,也就是我們所說的多型性。
對於Java而言,它多型的實現機制遵循一個原則:當超類物件引用變數引用子類物件時,被引用物件的型別而不是引用變數的型別決定了呼叫誰的成員方法,但是這個被呼叫的方法必須是在超類中定義過的,也就是說被子類覆蓋的方法。
二. 多型的實現方式
方式一:重寫
方式二:介面
方式三:抽象類和抽象方法
package com.zth;
abstract class Animal{
abstract void eat();
}
class Cat extends Animal{
public void eat() {
System.out.println("貓吃魚");
}
public void work() {
System.out.println("抓老鼠");
}
}
class Dog extends Animal{
public void eat() {
System.out.println("吃骨頭");
}
public void work() {
System.out.println("看家");
}
}
public class Test{
public static void main(String[] args) {
show(new Cat()); // 以 Cat 物件呼叫 show 方法
show(new Dog()); // 以 Dog 物件呼叫 show 方法
Animal a = new Cat(); // 向上轉型
a.eat(); // 呼叫的是 Cat 的 eat
Cat c = (Cat)a; // 向下轉型
c.work(); // 呼叫的是 Cat 的 work
}
public static void show(Animal a) {
if(a instanceof Cat) {
Cat c = (Cat)a;
c.work();
}else if(a instanceof Dog){
Dog c = (Dog)a;
c.work();
}
}
}
執行結果:
抓老鼠
看家
貓吃魚
抓老鼠