22. 多態(tài)

Java三大特性有封裝、繼承、多態(tài)。

前面我們已經(jīng)學(xué)過了封裝和繼承,今天學(xué)習(xí)多態(tài),如需前面內(nèi)容的可自行查看。

1、多態(tài)的引入

多態(tài)是繼封裝、繼承之后,面向?qū)ο蟮牡谌筇匦?/strong>

生活中,比如交通工具的種類可以分為飛機(jī)、汽車、輪船

再比如交通工具的運(yùn)行方式飛機(jī)運(yùn)行方式是飛在天上、汽車是在馬路上開、輪船是在海上行駛

可見,同一行為,通過不同的事物,可以體現(xiàn)出來的不同的形態(tài)

多態(tài),描述的就是這樣的狀態(tài)。

2、多態(tài)性的概念

2.1 多態(tài)的含義

多態(tài)性是面向?qū)ο蟮娜筇卣髦?,同一行為,通過不同的事物,可以體現(xiàn)出來的不同的形態(tài)。

2.2 Java中多態(tài)的具體體現(xiàn)

  • 方法重載(在同一個(gè)類中,同名的方法,由于形參的不同,實(shí)現(xiàn)方法的重載,在調(diào)用方法時(shí),可根據(jù)實(shí)參的組合來選擇所調(diào)用的方法)
  • 方法覆蓋(主要在繼承時(shí)用到,子類繼承父類,可以重寫父類的非靜態(tài)的方法)
  • 多態(tài)參數(shù)(新內(nèi)容,重點(diǎn)、難點(diǎn),本章主要講)

2.3 多態(tài)的前提

  1. 存在繼承或者實(shí)現(xiàn)關(guān)系
  2. 子類或?qū)崿F(xiàn)類必須重寫父類方法
  3. 父類引用指向子類對(duì)象

2.4 父類引用指向子類對(duì)象

提個(gè)概念,編譯器類型指的是‘=’左邊的類型,運(yùn)行期類型指的是‘=’右邊的類型。

當(dāng)有繼承關(guān)系時(shí),可能發(fā)生編譯期類型和運(yùn)行期類型不同的情況,即編譯期類型是父類類型,運(yùn)行期類型是子類類型。

即:父類引用指向子類對(duì)象

例如:

//動(dòng)物類

public class Animal {
    private String name;
    
    public Animal() {
        // TODO Auto-generated constructor stub
        this.name = "動(dòng)物";
    }
    public void eat() { 
        System.out.println("動(dòng)物在吃");
    }
    
    static void look() {
        System.out.println("動(dòng)物在看");
    }
    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }   
}

//狗類

public class Dog extends Animal {
    private String name;
    
    public Dog() {
        // TODO Auto-generated constructor stub
        this.name = "狗";
    }
    public void eat() {
        System.out.println("狗在吃");
    }
    
    public void bite() {
        System.out.println("狗咬人");
    }
    
    static void look() {
        System.out.println("狗在看");
    }
    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

//測(cè)試類:

public class Demo {

    public static void main(String[] args) {
        // 父類對(duì)象指向子類引用
        Animal animal = new Dog();

        // 如果子類中重寫了父類的方法,按照子類重寫的方法執(zhí)行
        animal.eat();

        // 子類自己擴(kuò)展的方法,不能調(diào)用
//      animal.bite();

        // 調(diào)用父類和子類同名的靜態(tài)方法,調(diào)用的是父類的靜態(tài)方法
        animal.look();

    }
}

3、多態(tài)參數(shù)

3.1 形參具有多態(tài)性

接著上述的案例,如果我們有個(gè)方法需要分別調(diào)用他們同名的方法,應(yīng)該怎么做呢?

比如:在Demo類中有個(gè)doing()方法,我想要傳進(jìn)來的對(duì)象,讓他們都執(zhí)行他們的eat()這個(gè)方法,此時(shí),我們就需要利用方法參數(shù)多態(tài)性。

我們只需要把形參的類型定義成父類的類型,我們可以利用上面提到過的驗(yàn)證(當(dāng)父類引用調(diào)用子類對(duì)象時(shí),調(diào)用重寫的方法,是執(zhí)行子類的重寫后方法)。

在一個(gè)方法的形參類型你設(shè)成父類類型,你傳入一個(gè)實(shí)參對(duì)象,如果是一個(gè)子類的對(duì)象就相當(dāng)于上述的父類引用調(diào)用子類對(duì)象,如果傳入的是父類對(duì)象那就是正常的編譯器類型等于運(yùn)行期類型情況,正常調(diào)用。

如此,我們就實(shí)現(xiàn)了形參的多態(tài)性,在很大程度上減少了代碼的重復(fù)性,也提高了代碼的擴(kuò)展性。

class Demo{
void doing(Animal a){
a.eat();
}
}

3.2 多態(tài)環(huán)境下對(duì)象造型

上述情況,只是描述對(duì)于一些子類重寫父類方法的調(diào)用,在第一個(gè)案例中,我們知道父類引用指向子類對(duì)象時(shí),沒有辦法調(diào)用子類擴(kuò)展的方法,那我們應(yīng)該怎么做了?

此時(shí),我們就需要用到我們?cè)趯W(xué)習(xí)數(shù)據(jù)類型時(shí)的一個(gè)概念,強(qiáng)制轉(zhuǎn)換,將父類引用強(qiáng)制轉(zhuǎn)換成子類的類型。

注意:強(qiáng)制轉(zhuǎn)換,只能是將父類類型轉(zhuǎn)換成運(yùn)行期類型,不能是別的類型。

不僅父類引用可以強(qiáng)制轉(zhuǎn)換成子類的類型,子類的引用也可以強(qiáng)制轉(zhuǎn)換成父類的類型。

造型方向上看,可分為:

(1)向上造型 –又稱自動(dòng)類型提升

    即父類引用指向子類對(duì)象,將子類對(duì)象向上造型成為父類類型。

    作用是:提高程序的擴(kuò)展性。

(2)向下造型 –又稱向下轉(zhuǎn)型

   即將子類對(duì)象強(qiáng)制轉(zhuǎn)換成父類類型

   作用:實(shí)現(xiàn)子類擴(kuò)展方法的調(diào)用。

例如:接著上述例子

//父類引用指向子類對(duì)象
Animal animal=new Dog();    
Dog dog = (Dog)animal;      //將父類引用強(qiáng)制轉(zhuǎn)換成子類的類型
dog.look();     //此時(shí)調(diào)用的子類的靜態(tài)方法
dog.bite();     //可以調(diào)用子類擴(kuò)展的方法

//子類引用指向子類對(duì)象
Dog dog1 = new Dog();
Animal a = (Animal)dog1;   //將子類引用轉(zhuǎn)換成父類類型
a.eat();           //調(diào)用的是子類的方法
a.look();          //調(diào)用的是父類的靜態(tài)方法
//a.bite();          //子類擴(kuò)展的方法不能調(diào)用

4、instanceof ()方法

4.1 instanceof 操作符

使用instanceof操作符來判斷一個(gè)對(duì)象的運(yùn)行期類型,即用來在運(yùn)行時(shí)指出對(duì)象是否是特定類的一個(gè)實(shí)例。

4.1 instanceof 用法

語法:

對(duì)象名稱 instanceof 類型;

返回值類型:布爾類型

Dog dog1 = new Dog();
Animal a = (Animal)dog1;
System.out.println(a instanceof Animal);

//結(jié)果:
true
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容