面向物件程式設計----多型_基本概念_強制轉型問題_instanceof運算子
多型
Polymorphism
在程式設計中,可以分為兩大階段,一個程式想要執行可以分為編譯和執行。
編譯:編譯的時候使用父類,把多種情況都列舉出來。如:說出多種情況
執行:執行的時候,只有一種情況,是什麼就是什麼。如:做現實的事情
多型性是OOP中的一個重要特性,主要是用來實現動態聯編的,換句話說,就是程式的最終狀態只有在執行過程中才被決定而非在編譯期間就決定了。
這對於大型系統來說能提高系統的靈活性和擴充套件性。
Java中如何實現多型?使用多型的好處?
引用變數的兩種型別:
編譯時型別(模糊一點,一般是一個父類)
由宣告時的型別決定。
執行時型別(執行時,具體是哪個子類就是哪個子類)
由實際對應的物件型別決定。
多型的存在要有3個必要條件:
要有繼承,要有方法重寫,父類引用指向子類物件。
package cn.bjsxt.oop.polymorphism;
/**
* animal動物
* @author 神奇的夢
*
*/
public class Animal {
public void voice() {
System.out.println("普通動物的叫聲");
}
}
class Cat extends Animal {
public void voice() {
System.out.println("喵喵喵");
}
public void catchMouse() {
System.out.println("抓老鼠");
}
}
class Dog extends Animal {
public void voice() {
System.out.println("汪汪汪");
}
public void seeDoor() {
System.out.println("看門");
}
}
class Tiger extends Animal {
public void voice() {
System.out.println("哼哼哼");
}
}
class Pig extends Animal {
public void voice() {
System.out.println("哼哼哼");
}
}
package cn.bjsxt.oop.polymorphism;
/**
*
* 多型是方法的多型,屬性沒有多型。
* @author 神奇的夢
*
*/
public class Test {
/**/
// 編譯時的型別由宣告時的型別決定
// Animal就包含了子類的集中情況 編譯時型別
在這裡是這麼回事Cat c = new Cat();Animal a=c;相當於Animal a=new Cat();
public static void testAnimalVoice(Animal c) {
// 通過呼叫例項化物件c找到裡面的方法voice方法
c.voice();
// instanceof判斷一個物件是不是這個型別的物件
// c是Cat類的例項物件
if(c instanceof Cat) {
// 編譯器不認,c還是Animal,所以要強轉為Cat
// 把c強轉為Cat然後呼叫catchMouse()抓老鼠方法
((Cat)c).catchMouse();
}
}
/*
public static void testAnimalVoice(Animal c,Animal dc,Animal p) {
// 通過呼叫例項化物件c找到裡面的方法voice方法
c.voice();
dc.voice();
p.voice();
// c.voicel();
}
*/
// public static void testAnimalVoice(Cat c) {
// 通過呼叫例項化物件c找到裡面的方法voice方法
// c.voice();
// c.voicel();
// }
/*
// 如果沒有多型可以這麼做
// 可以呼叫類Cat的過載方法
// 編譯時的型別由宣告是的型別決定
public static void testAnimalVoice(Cat c) {
// 通過呼叫例項化物件c找到裡面的方法voice方法
c.voice();
}
// 編譯時的型別由宣告是的型別決定
// 可以呼叫類Dog的過載方法
public static void testAnimalVoice(Dog c) {
// 通過呼叫例項化物件c找到裡面的方法voice方法
c.voice();
}
// 編譯時的型別由宣告是的型別決定
// 可以呼叫PIg的過載方法
public static void testAnimalVoice(Pig c) {
// 通過呼叫例項化物件c找到裡面的方法voice方法
c.voice();
}*/
// 如果有十個類寫十個方法就可以了
public static void main(String[] args) {
// new一個模板物件c
// new Cat()相當於執行時型別,實際上是一個Cat
// 編譯時的型別由宣告是的型別決定
Cat t = new Cat();
testAnimalVoice(t);
// Cat繼承於Animal實際上也屬於Animal的一個子類
// Cat c = new Cat();
// Animal a=c;
// Cat c = new Cat();Animal a=c;相當於Animal a=new Cat();
// 這樣就構成一個多型了
// 父類的引用Animal指向了一個子類的物件
// 想要執行必須先要通過編譯
// 編譯器只認宣告類 寫的是Animal 它就是Animal 別的它不管它只管編譯
Animal a=new Cat();
// 父類的引用Animal指向了一個子類的物件
Animal b=new Dog();
// 父類的引用Animal指向了一個子類的物件
Animal c=new Pig();
Animal d=new Tiger();
呼叫重寫後的繼承子類
一個類裡面只有一個方法可以這樣呼叫
testAnimalVoice(a);
testAnimalVoice(b);
testAnimalVoice(c);
一個類裡面有多個方法這樣呼叫
// The method catchMouse() is undefined for the type Animal
// 型別Animal的方法catchMouse()未定義
// a.catchMouse();//怎麼轉型呢
// 強制轉型
// 將變數a強制型別轉換為(Cat)類
Cat a2 =(Cat)a;
// 呼叫變數例項化a2裡面的方法catchMouse()
a2.catchMouse();
a2.voice();
// 型別不一樣 轉不了,更調不了 是錯的
Cat ca2 =(Cat)c;
// 呼叫變數例項化a2裡面的方法catchMouse()
ca2.catchMouse();
// 給普通方法testAnimalVoice()傳參物件c
// 通過例項化物件c傳參為區域性變數從而呼叫方法內c.voice()方法
// testAnimalVoice(c);
Dog dc = new Dog();
// 給普通方法testAnimalVoice()傳參物件dc
// 通過例項化物件dc傳參為區域性變數c從而呼叫方法內c.voice()方法
// testAnimalVoice(dc);
Pig p = new Pig();
// testAnimalVoice(p);
// testAnimalVoice(c,dc,p);
}
}