多態(tài)中的向上轉(zhuǎn)型與向下轉(zhuǎn)型

在討論向上轉(zhuǎn)型和向下轉(zhuǎn)型之前,先復(fù)習下多態(tài)运嗜。如果有錯誤的地方,希望能夠指出反惕,大家共同進步驮宴!

什么是多態(tài)雏掠?

多態(tài)(Polymorphism)即同一操作作用于不同的對象中鼠,可以有不同的解釋援雇,產(chǎn)生不同的結(jié)果。

多態(tài)的分類

多態(tài)一般分為兩種:

  1. 重載式多態(tài)

    • 重載式多態(tài)椎扬,也叫編譯時多態(tài)惫搏。也就是說這種多態(tài)在編譯時已經(jīng)確定好了筐赔。方法名相同而參數(shù)列表不同的一組方法就是重載揖铜。在調(diào)用這種重載的方法時汰规,通過傳入不同的參數(shù)最后得到不同的結(jié)果餐茵。
  2. 重寫式多態(tài)

    • 重寫式多態(tài)述吸,也叫運行時多態(tài)忿族。這種多態(tài)通過動態(tài)綁定(dynamic binding)技術(shù)來實現(xiàn),是指在執(zhí)行期間判斷所引用對象的實際類型朴读,根據(jù)其實際的類型調(diào)用其相應(yīng)的方法屹徘。也就是說,只有程序運行起來衅金,你才知道調(diào)用的是哪個子類的方法噪伊。這種多態(tài)通過函數(shù)的重寫以及向上轉(zhuǎn)型來實現(xiàn)。

多態(tài)實現(xiàn)的必要條件

  1. 繼承或?qū)崿F(xiàn)接口

    • 在多態(tài)中必須存在有繼承關(guān)系的子類和父類或者接口及其實現(xiàn)類
  2. 重寫

    • 子類對父類中某些方法進行重新定義氮唯,再調(diào)用這些方法時就會調(diào)用子類的方法
  3. 向上轉(zhuǎn)型

    • 父類引用指向子類對象叫做向上轉(zhuǎn)型鉴吹。

向上轉(zhuǎn)型與向下轉(zhuǎn)型

向上轉(zhuǎn)型,上面已經(jīng)說了惩琉,向下轉(zhuǎn)型是子類引用指向父類對象(父類型豆励,實例是子類的實例化),通常需要進行強制類型轉(zhuǎn)換

案例

//水果類瞒渠,擁有一個show()方法
class Fruits {

    public void show() {
        System.out.println("我水果之父良蒸,打錢!");
    }

}
// 蘋果類,實現(xiàn)父類水果伍玖,并重寫show()方法
class Apple extends Fruits {

    @Override
    public void show() {
        System.out.println("我蘋果嫩痰,打錢!");
    }

    public void color() {
        System.out.println("我是紅色的蘋果。");
    }
}
// 香蕉類窍箍,實現(xiàn)父類水果串纺,并重寫show()方法
class Banana extends Fruits {
    @Override
    public void show() {
        System.out.println("我香蕉,打錢!");
    }

    public void color() {
        System.out.println("我是黃色的香蕉椰棘。");
    }
}
//測試類
public class Test {

    public static void main(String[] args) {
        //向上轉(zhuǎn)型
        Fruits fruit = new Apple();

        fruit.show();

        fruit = new Banana();

        fruit.show();

    }

}

/**
運行結(jié)果:
    我蘋果纺棺,打錢!
    我香蕉,打錢!
*/

這就是向上轉(zhuǎn)型晰搀,Fruits fruit = new Apple();將子類對象Apple轉(zhuǎn)化為父類對象Fruits五辽,這個時候fruit引用指向的是子類對象,所以調(diào)用的方法是子類方法外恕。

向上轉(zhuǎn)型的好處

  • 減少重復(fù)代碼
  • 提高代碼擴展性

向上轉(zhuǎn)型需要注意的問題

向上轉(zhuǎn)型時杆逗,子類單獨定義的方法會丟失。比如鳞疲,上面案例中的Apple類和Banana類都定義了自己的color方法罪郊,當進行了向上轉(zhuǎn)型后,fruit引用指向Apple類的實例時是訪問不到color方法的尚洽,fruit.color()會報錯悔橄。

向下轉(zhuǎn)型

子類引用指向父類對象(父類型,實例是子類的實例化)腺毫,通常需要進行強制類型轉(zhuǎn)換癣疟,但是這里有個需要注意的問題。

//還是上面的Fruits潮酒、Apple睛挚、Banana

Fruits fruit = new Apple(); //向上轉(zhuǎn)型

Apple apple = (Apple)fruit; //向下轉(zhuǎn)型,強制類型轉(zhuǎn)換

apple.color();  //輸出:我是紅色的蘋果急黎。

Banana banana = (Banana) fruit; //報錯:java.lang.ClassCastException

Fruits f1 = new Fruits();

Apple a1 = (Apple) f1;  //報錯:java.lang.ClassCastException

為什么Apple apple = (Apple)fruit;沒有報錯可以轉(zhuǎn)換成功呢扎狱?因為apple本身就是Apple對象,所以理所當然可以向下轉(zhuǎn)型為Apple勃教,所以自然也就不能轉(zhuǎn)換成Banana淤击,人可以干出指鹿為馬的事情,但是編譯器不行故源,不會指著蘋果說是香蕉污抬。

而f1是Fruits對象,它也不能被向下轉(zhuǎn)型為任何子類對象绳军,就好比你買了一個不知名的水果印机,你只知道它是一種水果,但是你不能直接說這個水果是蘋果或者香蕉删铃。

向下轉(zhuǎn)型需要注意的問題

  • 向下轉(zhuǎn)型的前提是父類引用指向的是子類對象耳贬,也就是說,向下轉(zhuǎn)型之前猎唁,它得先進行過向上轉(zhuǎn)型咒劲。
  • 向下轉(zhuǎn)型只能轉(zhuǎn)型為本類對象(蘋果是不能變成香蕉的)。

多態(tài)的經(jīng)典案例

簡單的多態(tài)和轉(zhuǎn)型诫隅,相信大家都會腐魂,最后來個復(fù)雜的,一個經(jīng)典案例:

class A {
    public String show(D obj) {
        return ("A and D");
    }

    public String show(A obj) {
        return ("A and A");
    }

}

class B extends A{
    public String show(B obj){
        return ("B and B");
    }

    public String show(A obj){
        return ("B and A");
    }
}

class C extends B{

}

class D extends B{

}

public class Demo {
    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));
    }
}

/**
輸出結(jié)果:
    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
*/

結(jié)果1逐纬、2蛔屹、3還好理解,從4開始就糊涂了豁生,4為什么不是“B and B”呢兔毒?

這里我們先看一句話:當父類對象引用變量引用子類對象時漫贞,被引用對象的類型決定了調(diào)用誰的成員方法,但是這個被調(diào)用的方法必須是在父類中定義過的育叁,也就是說被子類覆蓋的方法迅脐。這句話對多態(tài)進行了一個概括,其實在繼承中對象方法的調(diào)用存在一個優(yōu)先級:this.show(O)豪嗽、super.show(O)谴蔑、this.show((super)O)、super.show((super)O)龟梦。

現(xiàn)在來分析一下4隐锭,a2.show(b)

  • a2是A類型的引用變量,this就代表了A计贰,但是a2所引用的是B對象(new B())钦睡,那么按照上面那句話的意思,a2.show(b)就應(yīng)該要調(diào)用B類中的show(B obj)蹦玫,產(chǎn)生的結(jié)果就是”B and B“赎婚,但是運行結(jié)果明顯不是,別忘了上面的話后面還有一句樱溉,必須是父類中定義過的方法才行挣输,然而B的父類A中并沒有show(B obj),難道上面的話是錯誤的福贞?其實不是撩嚼,因為它仍然要按照繼承鏈中調(diào)用方法的優(yōu)先級來確定,所以它才會在A類中找到show(A obj)挖帘,由于B中重寫了該方法完丽,所以才會調(diào)用B類中的方法,所以得到的結(jié)果是B and A拇舀。
  • 上面的解釋可能有點繞逻族,很多大佬在博客中也是這么寫的,現(xiàn)在我來說說自己的理解骄崩。A a2 = new B();這行代碼進行了向上轉(zhuǎn)型聘鳞,前面說過向上轉(zhuǎn)型之后,子類單獨定義的方法會丟失(不能被調(diào)用)要拂,那么這個時候a2可以調(diào)用的方法就剩下A類中的show(D obj)抠璃、show(A obj)以及B類中的show(A obj),那么按照繼承鏈中調(diào)用方法的優(yōu)先級來判斷脱惰,先到類A中找到show(A obj)搏嗡,由于B類中進行了重寫 ,所以調(diào)用的是B類中的show(A obj)拉一。

那么按照我的理解采盒,來分析下5旧乞,a2.show(c)

  • 首先A a2 = new B();進行向上轉(zhuǎn)型纽甘,那么良蛮,a2能調(diào)用的方法還是A類中的show(D obj)抽碌、show(A obj)以及B類中的show(A obj)悍赢,按照繼承鏈中調(diào)用方法的優(yōu)先級,a2是A類型的引用變量货徙,所以繼承鏈方法調(diào)用優(yōu)先級中this.show(O)的this就代表了A左权,顯然A類中的方法不滿足這個要求,跳過痴颊,所以接下來是super.show(O)赏迟,A類沒有父類(除了Object類),再次跳過蠢棱,然后是this.show((super)O)锌杀,C繼承于B,B繼承于A泻仙,所以show(A obj)滿足要求糕再,由于a2變量引用的對象類型是B類型,而B類型又重寫了該方法玉转,所以最終調(diào)用的是B類中的show(A obj)突想,所以最后輸出為B and A

能夠分析出4和5究抓,那么接下來的就很簡單了猾担,看到這篇文章的話,可以自己試著分析下刺下。如果有錯誤的地方绑嘹,希望能夠指出,大家共同進步橘茉!

如果對你有幫助工腋,點擊鏈接,關(guān)注一下吧捺癞!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末夷蚊,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子髓介,更是在濱河造成了極大的恐慌惕鼓,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件唐础,死亡現(xiàn)場離奇詭異箱歧,居然都是意外死亡矾飞,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進店門呀邢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來洒沦,“玉大人,你說我怎么就攤上這事价淌∩暄郏” “怎么了?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵蝉衣,是天一觀的道長括尸。 經(jīng)常有香客問我,道長病毡,這世上最難降的妖魔是什么濒翻? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮啦膜,結(jié)果婚禮上有送,老公的妹妹穿的比我還像新娘。我一直安慰自己僧家,他們只是感情好雀摘,可當我...
    茶點故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著啸臀,像睡著了一般届宠。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上乘粒,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天豌注,我揣著相機與錄音,去河邊找鬼灯萍。 笑死轧铁,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的旦棉。 我是一名探鬼主播齿风,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼绑洛!你這毒婦竟也來了救斑?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤真屯,失蹤者是張志新(化名)和其女友劉穎脸候,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡运沦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年泵额,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片携添。...
    茶點故事閱讀 40,133評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡嫁盲,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出烈掠,到底是詐尸還是另有隱情羞秤,我是刑警寧澤,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布向叉,位于F島的核電站锥腻,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏母谎。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一京革、第九天 我趴在偏房一處隱蔽的房頂上張望奇唤。 院中可真熱鬧,春花似錦匹摇、人聲如沸咬扇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽懈贺。三九已至,卻和暖如春坡垫,著一層夾襖步出監(jiān)牢的瞬間梭灿,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工冰悠, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留堡妒,地道東北人。 一個月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓溉卓,卻偏偏與公主長得像皮迟,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子桑寨,可洞房花燭夜當晚...
    茶點故事閱讀 45,077評論 2 355

推薦閱讀更多精彩內(nèi)容