多態
需求分析
養了多隻動物, 每一個動物生病之後, 需要提供相應的方法 ,
給寵物看病, 寵物越多, 方法越多 , 每添加一個寵物, 就需要添加一個方法
弊端: 頻繁修改代碼, 可擴展性和可維護性差
// 給狗看病的方法
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);