自學Java之day10_java之多態性

多態的概述

多態是繼封裝、繼承之後,面向對象的第三大特性。 生活中,比如跑的動作,小貓、小狗和大象,跑起來是不一樣的。再比如飛的動作,昆蟲、鳥類和飛機,飛起來也 是不一樣的。可見,同一行爲,通過不同的事物,可以體現出來的不同的形態。多態,描述的就是這樣的狀態。一個對象擁有多種形態,這就是對象的多態性。例如:小明是一個學生(學生形態),但也是一個人(人類形態)。

定義

多態: 是指同一行爲,具有多個不同表現形式。

前提

  • 繼承或者實現【二選一】
  • 方法的重寫【意義體現:不重寫,無意義】
  • 父類引用指向子類對象【格式體現】

多態的體現

多態體現的格式:

  • 父類名稱 變量名 = new 子類對象;

或者

  • 接口名稱 對象名 = new 實現類名稱();

多態中成員變量的訪問特點

訪問成員變量的兩種方式:

  • 直接通過對象名稱訪問成員變量名稱:看等號左邊是誰,優先用誰,沒有則向上找。
  • 間接通過成員方法訪問成員變量名稱:看該方法屬於誰,優先用誰,沒有則向上找。

多態中的成員方法的訪問特點

當使用多態方式調用方法時,首先檢查父類中是否有該方法,如果沒有,則編譯錯誤;如果有,執行的是子類重寫 後方法  口訣:編譯看左邊,運行看右邊。

在多態的代碼當中,成員方法的訪問規則是:看new的是誰,就優先用誰,沒有則向上找。

對比:

  • 成員變量:編譯看左邊,運行還看左邊。
  • 成員方法:編譯看左邊,運行看右邊。

代碼舉例

定義父類Father

package myDemo02;

public class Father {
    //定義成員變量
    String name = "張三";
    //定義成員方法
    public void method() {
        System.out.println();
        System.out.println("我是父類中的方法");
    }

    public void methodFather() {
        System.out.println("我是父類中獨有的方法,我的名字是" + name);
    }

}

定義子類Son

package myDemo02;

public class Son extends Father {
    //定義子類成員變量
    String name = "李四";
    @Override
    //重寫父類的成員方法
    public void method() {
        System.out.println("我重寫了父類中的方法,我的名字是:" +name);

    }
}

定義測試類MyMultiTest

package myDemo02;

public class  {
    public static void main(String[] args) {
        /*父類類型 變量名 = new 子類對象;
         父類類型:指子類對象繼承的父類類型,或者實現的父接口類型。
        */
        //多態寫法
        Father multi = new Son();
        //調用子父類重名的方法,編譯看父類,實際運行子類中的方法,
        multi.method();
        //調用父類中獨有的方法:編譯看父類,因爲子類中沒有相同的方法,所以向上查找
        multi.methodFather();
        //訪問子父類重名成員變量,等號左邊的是誰,優先使用誰的成員變量
        String name = multi.name;
        System.out.println(name);
    }
}

代碼執行後的結果

多態的好處

實際開發的過程中,父類類型作爲方法形式參數,傳遞子類對象給方法,進行方法的調用(多態規定,執行的是子類重寫的方法),更能體現出多態的擴展 性與便利。

引用類型轉換

多態的轉型分爲向上轉型與向下轉型兩種:

向上轉型

向上轉型:多態本身是子類類型向父類類型向上轉換的過程,這個過程是默認的。 當父類引用指向一個子類對象時,便是向上轉型。 向上轉型一定是安全的。

使用格式:父類類型 變量名 = new 子類類型();  

含義:創建一個子類對象,把它當做父類來看待使用

例如

// 創建了一個dog對象,把它看成是動物,沒有如何問題
      Animal animal = new Dog();

向下轉型

向下轉型:父類類型向子類類型向下轉換的過程,這個過程是強制的。 一個已經向上轉型的子類對象,將父類引用轉爲子類引用,可以使用強制類型轉換的格式,便是向下轉型。

使用格式:子類類型 變量名 = (子類類型) 父類變量名;

含義:將父類對象還原成爲本來的子類對象

例如:

//將動物對象,還原成爲本來的dog對象 
Dog dog = (Dog) animal;

注意事項:

必須保證對象創建的時候就dog對象,才能向下轉型爲dog。否則運行時,卻報出了 ClassCastException ,類型轉換異常!

爲什麼要轉型

當使用多態方式調用方法時,首先檢查父類中是否有該方法,如果沒有,則編譯錯誤。也就是說,不能調用子類擁 有,而父類沒有的方法。編譯都錯誤,更別說運行了。這也是多態給我們帶來的一點"小麻煩"。所以,想要調用子 類特有的方法,必須做向下轉型。

向下轉型容易發生的問題

如果創建了A 對象,卻把它向下轉型成爲B 對象,在運行時,會報出了 ClassCastException ,類型轉換異常!爲了避免ClassCastException的發生,Java提供了 instanceof 關鍵字,給引用變量做類型的校驗,格式如下:

  • 變量名 instanceof 數據類型
  • 如果變量屬於該數據類型,返回true
  • 如果變量不屬於該數據類型,返回false

代碼舉例

定義接口Animal

package myDemo04;
//定義接口
public interface Animal {
    //定義抽象方法
    public abstract void eat();
}

定義實現類Cat

package myDemo04;

public class Cat implements  Animal{
    @Override
    public void eat() {
        System.out.println("我喜歡吃魚");
    }
    public void CatRun(){
        System.out.println("我是貓,跑起來沒有聲音");
    }
}

定義實現類Dog

package myDemo04;

public class Dog implements Animal {
    @Override
    public void eat() {
        System.out.println("我喜歡吃骨頭");
    }
    public void DogRun(){
        System.out.println("我是狗,跑的好快好快");
    }
}

定義測試類

package myDemo04;

public class Test {
    public static void main(String[] args) {
        //父類引用指向子類對象就是向上轉型:
        Animal animal = new Dog();
        //調用方法,編譯看左,運行看右
        animal.eat();
        //  Cat cat = (Cat) animal;創建了Dog對象,轉換爲Cat對象,運行會報ClassCastException ,類型轉換異常!
        if (animal instanceof Dog) {
            //將父類引用轉爲子類引用,便是向下轉型。
            Dog dog = (Dog) animal;
            //調用子類中特有的方法
            dog.DogRun();
        }
        if (animal instanceof Cat) {
            //將父類引用轉爲子類引用,便是向下轉型。
            Cat cat = (Cat) animal;
            //調用子類中特有的方法
            cat.CatRun();
        }

    }
}

代碼執行後的結果

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章