Java的多态淺談
概述
Java的四大基本特性:抽象,封裝,繼承和多态。其中,抽象,封裝,繼承可以說多态的基礎,而多态是封裝,繼承的具體表現。如果非要用專業術語來描述什麼是多态的話
多态是指程式中定義的引用變量所指向具體類型和通過該引用變量發出的方法調用在編譯的時候并不确定,而是程式運作期間才确定,就是說一個引用變量到底指向哪一個類的執行個體對象,該引用變量發出的方法調用哪一個類的中的方法,必須在程式運作期間才能确定。
記得大學時老師講多态舉的一個例子:上課鈴響了,同學們都回各自教室上課,這就是多态。這就完了?如果是剛接觸程式設計的同學來說,估計都懵逼了,我們那時就是這種狀态。接下來我們用代碼實作下老師說的意思。
多态執行個體
//上課鈴響了
public class Ring
{
public void ringSound()
{
System.out.println("我是鈴聲!!!");
}
}
1班的同學聽到鈴聲回去上國文課
public class ClassRoom1 extends Ring
public void ringSound()
{
System.out.println("classRoom1的同學聽到鈴聲上國文了!!!");
}
2班的同學聽到鈴聲回去上英語課
public class ClassRoom2 extends Ring
public void ringSound()
{
System.out.println("classRoom2的同學聽到鈴聲上英語了!!!");
}
Main類
public class Main
public static void main(String[] args)
{
Ring ring = new ClassRoom1();
Ring ring1 = new ClassRoom2();
ring.ringSound();
ring1.ringSound();
}
輸出
classRoom1的同學聽到鈴聲上國文了!!!
classRoom2的同學聽到鈴聲上英語了!!!
這就是一個簡單的的多态例子,我們從中不難發現,多态存在的幾個關鍵點,
有繼承關系(extends)
子類重寫父類方法(ringSound)
父類引用指向子類對象 Ring ring = new ClassRoom1()
現在我們改下例子,看出現什麼情況
public static void ringSound()
{
System.out.println("我是鈴聲!!!");
}
這時發現ClassRoom1 和 ClassRoom2 都報錯了,那我們也給他們都加上static
public static void ringSound()
{
System.out.println("classRoom1的同學聽到鈴聲上國文了!!!");
}
ClassRoom2類
public static void ringSound()
{
System.out.println("classRoom2的同學聽到鈴聲上英語了!!!");
}
預編譯沒報錯了,那麼輸出應該是剛才的結果,main函數跑起來,輸出
我是鈴聲!!!
可以發現,結果并不是我們所想的那樣。我們可以得出一個結論:在Java中static修飾的函數不能被子類重寫。
其實Java中,父類含有一個靜态函數,而且在他的子類也同樣有一個傳回類型,函數名,參數清單都相同的靜态函數,子類實際上隻是将父類中的該同名函數進行隐藏,而非重寫,他們兩個是完全沒有關系的函數,是以他們的行為并不具有多态性。
注意:就是被final修飾的父類函數是無法被重寫和private修飾的父類函數無法被繼承。這是Java的規定,就不在舉例說明
多态的作用
說了這麼多,多态有什麼作用
解耦,各種設計模式大多是基于多态實作的
複用性,子類處理父類即可
擴充和維護
多态缺點:不能使用子類的特有屬性和行為。
多态分類
為了确定執行多态函數的哪一個,是以有兩種情況:編譯時多态,運作時多态
函數重載都是編譯時多态,根據實際參數的資料類型,個數和順序,Java在編譯時就能夠确定執行重載函數中的哪一個。
函數重寫表現出兩種多态性,當對象引用本類執行個體時,為編譯時多态,否則為運作時多态。
public void ringSound()
{
System.out.println("我是鈴聲!!!");
}
public static void main(String[] args)
{
ClassRoom2 ring1 = new ClassRoom2();//編譯時多态,執行Ring類的ringSound
ring1.ringSound(); //編譯時多态,執行ClassRoom2 類的ringSound
Ring ring = new ClassRoom2();
ring.ringSound(); //運作時多态,是運作Ring的 ringSound 還是 ClassRoom2 類的ringSound 隻有運作時在确定。
}
花木蘭替父從軍(
https://www.zhihu.com/question/30082151/answer/120520568)
花木蘭替父親花弧從軍。那麼這時候花木蘭是子類,花弧是父類。花弧有自己的成員屬性年齡,姓名,性别。花木蘭也有這些屬性,但是很明顯二者的屬性完全不一樣。花弧有自己的非靜态成員方法‘騎馬殺敵’,同樣花木蘭也遺傳了父親一樣的方法‘騎馬殺敵’。花弧還有一個靜态方法‘自我介紹’,每個人都可以問花弧姓甚名誰。同時花木蘭還有一個自己特有的非靜态成員方法‘塗脂抹粉’。但是,現在花木蘭替父從軍,女扮男裝。這時候相當于父類的引用(花弧這個名字)指向了子類對象(花木蘭這個人),那麼在其他類(其他的人)中通路子類對象(花木蘭這個人)的成員屬性(姓名,年齡,性别)時,其實看到的都是花木蘭她父親的名字(花弧)、年齡(60歲)、性别(男)。當通路子類對象(花木蘭這個人)的非靜态成員方法(騎馬打仗)時,其實都是看到花木蘭自己運用十八般武藝在騎馬打仗。當通路花木蘭的靜态方法時(自我介紹),花木蘭自己都是用她父親的名字資訊在向别人作自我介紹。并且這時候花木蘭不能使用自己特有的成員方法‘塗脂抹粉’。 -----------多态中的向上造型
那麼終于一将功成萬骨枯,打仗旗開得勝了,花木蘭告别了戰争生活。有一天,遇到了自己心愛的男人,這時候愛情的力量将父類對象的引用(花弧這個名字)強制轉換為子類對象本來的引用(花木蘭這個名字),那麼花木蘭又從新成為了她自己,這時候她完全是她自己了。名字是花木蘭,年齡是28,性别是女,打仗依然那樣生猛女漢子,自我介紹則堂堂正正地告訴别人我叫花木蘭。OMG!終于,終于可以使用自己特有的成員方法‘塗脂抹粉’了。從此,花木蘭完全回到了替父從軍前的那個花木蘭了。并且和自己心愛的男人幸福的過完了一生。 ------多态中的向下轉型
花弧
public class HuaHu
int age = 60;
String name = "花弧";
String sex = "男";
public void horseKillEnemy()
{
System.out.println("騎馬殺敵");
}
public static void suggest()
{
System.out.println("我叫花弧");
}
花木蘭
public class HuaMuLan extends HuaHu
String name = "花木蘭";
int age = 28;
String sex = "女";
public void horseKillEnemy()
{
System.out.println("花木蘭騎馬殺敵");
}
public void Prettify()
{
System.out.println("花木蘭塗脂抹粉");
}
替父從軍
public static void main(String[] args)
{
//替父從軍
HuaHu huaHu = new HuaMuLan();
System.out.println("姓名:" + huaHu.name + ",年齡:" + huaHu.age + ",性别:" + huaHu.sex); //其他人
huaHu.horseKillEnemy();
huaHu.suggest(); //用她父親的名字資訊在向别人作自我介紹
//huaHu.Prettify() //無法使用
// 戰争結束了
HuaMuLan huaMuLan = (HuaMuLan)huaHu;
//花木蘭變回自己
System.out.println("姓名:" + huaMuLan.name + ",年齡:" + huaMuLan.age + ",性别:" + huaMuLan.sex);
//自己特有函數
huaMuLan.Prettify();
System.out.println("幸福的過完了一生");
}
姓名:花弧,年齡:60,性别:男
花木蘭騎馬殺敵
我叫花弧
姓名:花木蘭,年齡:28,性别:女
花木蘭塗脂抹粉
幸福的過完了一生
最後看個經典的多态例子
A類
public class A
public String show(D obj) {
return ("A and D");
}
public String show(A obj) {
return ("A and A");
}
B類
public class B extends A
public String show(B obj){
return ("B and B");
}
public String show(A obj){
return ("B and A");
}
C類
public class C extends B
D類
public class D extends B
public static void main(String[] args) {
A a1 = new A();
A a2 = new B();
B b = new B();
C c = new C();
D d = new D();
System.out.println("1--" + a1.show(b));
System.out.println("2--" + a1.show(c));
System.out.println("3--" + a1.show(d));
System.out.println("4--" + a2.show(b));
System.out.println("5--" + a2.show(c));
System.out.println("6--" + a2.show(d));
System.out.println("7--" + b.show(b));
System.out.println("8--" + b.show(c));
System.out.println("9--" + b.show(d));
}
1--A and A
2--A and A
3--A and D
4--B and A
5--B and A
6--A and D
7--B and B
8--B and B
9--A and D
你做對了嗎?
原文位址
https://www.cnblogs.com/dslx/p/10570559.html