07- 面向對象之多態

多態

需求分析

養了多隻動物, 每一個動物生病之後, 需要提供相應的方法 ,

給寵物看病, 寵物越多, 方法越多 , 每添加一個寵物, 就需要添加一個方法

弊端: 頻繁修改代碼, 可擴展性和可維護性差

// 給狗看病的方法
public void cure(Dog dog){
    System.out.println("給"+dog.name+"看病 ");
}
// 給貓看病
public void cure(Cat cat){
    System.out.println("給"+cat.name+"看病 ");
}
//給豬看病
public void cure(Pig pig){
    System.out.println("給"+pig.name+"看病 ");
}

優化之後

// 給動物看病的方法
public void cure(Animal animal){
    System.out.println("給"+animal.name+"看病 ");
}

多態的使用

父類的變量 指向 子類的對象
Animal animal = new Dog();  // Dog dog = new Dog();

回顧基本數據類型

int a = 10;
long b = a;

作用案例

參數列表是父類的情況

Person person= new Person();

Dog dog = new Dog();
dog.name = "旺財";
// 人給動物看病
person.cure(dog);

Cat cat = new Cat();
cat.name = "Tom";
// 人給動物看病
person.cure(cat);

返回值爲父類的情況(人去買寵物)

// 客戶 需要告訴商家 要買什麼寵物
public Animal sell(String type){
    if(type.equals("dog")){
        Dog dog = new Dog();
        dog.name = "來福";
        return dog;
    }else if(type.equals("cat")){
        Cat cat = new Cat();
        cat.name = "hello kitty";
        return cat;
    }else{
        Pig pig = new Pig();
        pig.name = "佩琪";
        return pig;
    }
}

優勢好處

屏蔽子類之間的差異

可替換性

可擴充性

接口性

靈活性

簡化性

多態注意事項

父類變量指向子類對象

兒子裝爹案例

父親 是 中醫大夫

兒子 學習 西醫

( 有人來看病- 該病人相信中醫大夫, 但是恰好中醫大夫不在家, 只有兒子在家 )

​ 兒子裝爹

新建father類

package date0712;

/**
 * 中醫大夫 (父親)
 */
public class Father {
    // 姓名
    String name = "扁鵲";
    // 年齡
    int age = 100;
    // 工具包 = 鍼灸包
    String instrument = "acupuncture";
    // 愛好
    String hobby = "喝茶";
    // 有瓷器(父親有 兒子沒有)
    String china = "景德鎮";

    // 娛樂活動
    public void play(){
        System.out.println("喝茶,看報,聽曲 !");
    }

    // 看病的方法
    public void cure(){
        System.out.println("望聞問切 ");
        System.out.println("使用中藥, 鍼灸 治療");
    }
    // 把脈的方法 (父親有 兒子沒有 , 兒子會默認繼承)
    public void pulse(){
        System.out.println("把脈");
    }
}

新建 son子類

package date0712;

/**
 * 西醫 (兒子)
 */
public class Son extends Father{
    // 姓名
    String name = "扁小鵲";
    // 年齡
    int age = 25;
    // 工具包 = 鍼灸包
    String instrument = "手術刀";
    // 愛好
    String hobby = "刷抖音,玩遊戲";
    // 電腦 (兒子有 父親沒有)
    String computer = "蘋果";

    //  (父類有play 方法, 如果兒子自己沒有play 默認繼承父類的)
    // 方法重寫  父類有該方法, 但是 兒子偏偏不喜歡 ()
    @Override
    public void play(){
        System.out.println("逛夜店, 蹦迪!");
    }
    // 看病的方法
    @Override
    public void cure(){
        System.out.println("聽診器 先進設備查一查 ");
        System.out.println("使用西藥,做手術");
    }
    // 做手術  (兒子有 父親沒有)
    public void operate(){
        System.out.println("做手術");
    }
}

方法和屬性的調用

public class Demo {
    public static void main(String[] args) {
        // 病人上門 找 中醫 , 只有西醫兒子在家
        // 兒子穿上父親的衣服  模擬父親的外貌
        Father father = new Son();

        System.out.println(father.name);
        System.out.println(father.age);
        System.out.println(father.instrument);
        System.out.println(father.hobby);
        System.out.println(father.china);
        /*
        對於屬性  父親有什麼 , 兒子纔能有什麼 (兒子只能使用父親有的東西)
        方法 父親有什麼方法, 兒子才能使用什麼方法
         */
        // System.out.println(father.computer);  //報錯

        father.pulse();
       //  father.operate();  // 手術方法 報錯
       // 編譯看左邊  編譯不報錯, 需要看賦值號左側 類型中有那些屬性和方法
       // 運行看右邊  當子類重寫了父類的方法之後 , 運行實際對象重寫之後的方法
        father.play();
        father.cure();
    }
}

編譯看左邊 編譯不報錯, 需要看賦值號左側 類型中有那些屬性和方法
運行看右邊 當子類重寫了父類的方法之後 , 運行實際對象重寫之後的方法

對象的向上和向下轉型

// 先卸下父親的僞裝 , 還原兒子的真面貌 , 纔可以去調用兒子的屬性和方法
Father father = new Son();
Son son = (Son) f1;

兒子 ==> 父親 向上轉型 (由小容器到大容器 ) 多態

父親 ==> 兒子 向下轉型 (由大容器到小容器) 需要先判斷 然後在轉型

instanceof

新建女兒類

public class Daughter extends Father{}
Father f1 = new Son();
Father f2 = new Daughter();
Son son = (Son) f1;
Daughter daughter = (Daughter) f2;
// 兒子和女兒之間不能 轉換 (否則會報類型轉換異常)
// java.lang.ClassCastException

避免類型轉換異常

// 判斷 f1 對象 是否可以轉換爲 Son 對象
System.out.println(f1 instanceof Son);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章