4、面向物件(二)
阿新 • • 發佈:2018-11-26
1、多型
多型簡介
多型就是事物存在的多種形態,比如你在大街上看見一隻藏獒,你可以說這隻藏獒真凶猛,也可以說這隻狗真凶猛,還可以說這個動物真凶猛,以上三種說法其實都是指的這隻藏獒。
在Java裡面,也是存在多型的,只要全部符合下面這三種情況,就是多型
- 有繼承
- 有方法重寫
- 有父類引用指向子類物件
例如下面程式碼就構成多型
class Animal{ public int num = 10; public void eat(){ System.out.println("動物再吃!"); } } class Cat extendsAnimal{ public int num = 20; public void eat(){ System.out.println("貓再吃!"); } } class Animal_Text{ public static void main(String[] args){ Animal m1 = new Cat();// 父親引用指向子類物件 m1.eat(); // 貓在吃 動態繫結和靜態繫結 System.out.println(m1.num); // 10 說明成員變數不存在 } }
靜態繫結和動態繫結
上面程式碼中,a1是Animal型別的一個引用,指向的是其子類Cat的物件,這個就叫做父類引用指向子類物件。程式在編譯的時候a1被看做Animal型別,所以a1.eat()繫結的是Animal類中的eat()方法,這叫做靜態繫結,程式執行時,a1指向的是堆中的Cat物件,而在Cat中對eat()方法進行了重寫,所以在執行階段繫結的是Cat中的eat()方法,這叫做動態繫結。
強制型別轉換
上面程式碼中子類向父型別進行轉換,是自動型別轉換,也叫做向上轉型。還有一種情況是父類向子型別轉換,是強制型別轉換,也叫向下轉型。下面的程式碼演示了強制型別轉換
classAnimal{ public int num = 10; public void eat(){ System.out.println("動物再吃!"); } } class Cat extends Animal{ public int num = 20; public void eat(){ System.out.println("貓再吃!"); } //Cat特有的方法. public void move(){ System.out.println("貓走路很輕盈!"); } } class Dog extends Animal{ //重寫 public void eat(){ System.out.println("狗啃骨頭!"); } } class Animal_Text{ public static void main(String[] args){ Animal a1 = new Cat();// 父親引用指向子類物件 //如果要是想執行Cat裡面的move方法該怎麼辦? //只能強制型別轉換,需要加強制型別轉換符 Cat c1 = (Cat)a1; c1.move(); Animal a2 = new Dog(); //向上轉型. //強制型別轉換 //Cat c2 = (Cat)a2; //會報錯 java.lang.ClassCastException } }
instanceof關鍵字
上面的程式碼裡面將一個指向Dog物件的Animal引用a2進行強制轉換成Cat型別時報出了ClassCastException類轉型錯誤,開發中要是想避免這種錯誤需要使用instanceof來判斷一下。
class Animal{ public int num = 10; public void eat(){ System.out.println("動物再吃!"); } } class Cat extends Animal{ public int num = 20; public void eat(){ System.out.println("貓再吃!"); } //Cat特有的方法. public void move(){ System.out.println("貓走路很輕盈!"); } } class Dog extends Animal{ //重寫 public void eat(){ System.out.println("狗啃骨頭!"); } } class Animal_Text{ public static void main(String[] args){ Animal a1 = new Cat();// 父親引用指向子類物件 //如果要是想執行Cat裡面的move方法該怎麼辦? //只能強制型別轉換,需要加強制型別轉換符 Cat c1 = (Cat)a1; c1.move(); Animal a2 = new Dog(); //向上轉型. //進行強制型別轉換時,需要先使用instanceof進行判斷,避免ClassCastException if (a2 instanceof Cat){ //強制型別轉換 Cat c2 = (Cat)a2; }else{ System.out.println("無法進行強制型別轉換"); } } }
多型的優點
- 提高了程式的擴充套件性
- 降低了程式碼之間的耦合
class Car{ public void run(){ System.out.println("汽車在行駛!"); } } class Benz extends Car{ public void run(){ System.out.println("賓士汽車在跑"); } } class BWM extends Car{ public void run(){ System.out.println("寶馬汽車再跑!"); } } class Person{ /* public void drive(Benz bc){ bc.run(); } 賓士汽車壞了,再重新建立一個開寶馬汽車的方法 public void drive(BMW bm){ bm.run(); } */ //上面程式碼擴充套件性太差,每新增加一種品牌的汽車就需要再寫一個方法 //將引數修改為Car型別,這樣不論增加什麼樣的品牌汽車,都可以呼叫這個方法 public void driver(Car c){ c.run(); } } public class Test{ public static void main(String[] args){ Person james = new Person(); //Benz bc = new Benz(); //james.drive(bc); BMW bm = new BMW(); james.drive(bm); } }