關(guān)于類的重寫多態(tài)

我們知道,面向?qū)ο笕筇匦岳?,封裝、繼承和多態(tài)里,多態(tài)是最復雜的。
多態(tài)的實現(xiàn)方式分為接口、重寫Override和重載Overload:
接口不用說了。
重寫Override是在父子類之間有相同的方法和參數(shù),是父子類的多態(tài)性。
重載Overload是一個類內(nèi)部有同名方法但是參數(shù)不同,是一個類的多態(tài)性。(重載在編譯期就能確定使用了那個函數(shù),所以不是運行時多態(tài),有些學派因此認為重載不算正宗的多態(tài))

這里面,重寫是一個難點,特別它的多態(tài)性是在運行時表現(xiàn)出來的,容易繞暈,一般來講,重寫多態(tài)是這樣的:

A a=new B();

a叫做引用變量,引用變量指向的具體類型和方法,在編譯時不能確定,是在運行時確定的。
重寫在多態(tài)上的表現(xiàn)就是具體指向哪個重寫方法:
首先,超類(A)中需要定義這個方法。
然后,引用對象(B)中定義了這個方法的最終形態(tài);

多態(tài)重寫有三個必要條件:
1.繼承
2.重寫
3.父類引用指向子類對象

我們先看規(guī)律,再根據(jù)兩個經(jīng)典例題來掌握規(guī)律的用法。

幾個規(guī)律

左右
變量多態(tài)看左邊,
靜態(tài)多態(tài)看左邊,
方法多態(tài)看右邊(左邊的方法表里需要有這個方法)。
優(yōu)先級
假設(shè)有個show(Object obj)函數(shù),那么對于show函數(shù)所在的類及其父類,已經(jīng)參數(shù)Object來說,有固定的優(yōu)先級(JVM虛擬機里的方法表查詢機制,決定了這個優(yōu)先級):
this.show(O)>>super.show(O)>>this.show(super(O))>>super.show(super(O)),這是虛擬機多態(tài)的機制里定義的優(yōu)先級,具體意思是說:

優(yōu)先使用當前類的定義this.show(O)
次優(yōu)先使用父類的定義super.show(O)
第三位使用當前類定義的父類參數(shù)函數(shù)this.show(super(O))
最后使用父類定義的父類參數(shù)函數(shù)super.show(super(O))

例題1

    public class A{
        void a(){
            System.out.print("Aa");
        }
        void b(){
            System.out.print("Ab");
        }
    }

    public class B extends A{
        void b(){
            System.out.print("Bb");
        }
        void d(){
            System.out.print("Bd");
        }
    }
    
    private void doTest(){
        A a=new B();
        a.a(); //Aa 只有A有實現(xiàn),不需要多態(tài)
        a.b(); //Bb 在子類B有實現(xiàn),多態(tài)
        a.d(); //A的方法表中沒有d,編譯錯誤
        B b=(B)a; //可以強轉(zhuǎn)
        b.a(); //Aa B沒有實現(xiàn),向父類A中尋找,并找到
        b.b(); //Bb B類的方法
        b.d(); //Bd B類的方法
    }

例題2

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

           return ("AA");
    } 
}   

class B extends A{
    public String show(B obj){
           return ("BB");
    }
    public String show(A obj){
           return ("BA");
    } 
}  
class C extends B{} 
class D extends B{}

//調(diào)用
A a1 = new A();
A a2 = new B();
B b = new B();
C c = new C(); 
D d = new D(); 

//其實就是考察從父類/參數(shù)多態(tài)的優(yōu)先級:this.show(O)>>super.show(O)>>this.show(super(O))>>super.show(super(O))

System.out.println(a1.show(b));  // ① AA,因為參數(shù)B是A,優(yōu)先級為this.show(super(O))
//相當于this.show(O)>>super.show(O)>>this.show(super(O)) 這里 >>super.show(super(O))

System.out.println(a1.show(c));  // ② AA,同上
System.out.println(a1.show(d));  // ③ AD,因為A定義了show(D obj),優(yōu)先級為this.show(O)
//相當于this.show(O)這里>>super.show(O)>>this.show(super(O)) >>super.show(super(O))

System.out.println(a2.show(b));  // ④ BA,因為A沒定義show(B obj),只能找到show(A obj),還是優(yōu)先級為this.show(super(O))
//相當于this.show(O)>>super.show(O)>>this.show(super(O)) 這里>>super.show(super(O))

System.out.println(a2.show(c));  // ⑤ AA,同上
System.out.println(a2.show(d));  // ⑥ AD,因為A定義了show(D obj),優(yōu)先級為this.show(O)
//相當于this.show(O)這里>>super.show(O)>>this.show(super(O)) >>super.show(super(O))

System.out.println(b.show(b));   // ⑦ BB,因為B定義了show(B obj),優(yōu)先級為this.show(O)
//相當于this.show(O)這里>>super.show(O)>>this.show(super(O)) >>super.show(super(O))

System.out.println(b.show(c));   // ⑧ BB,因為B定義了show(B obj),優(yōu)先級為this.show(super(O))
//相當于this.show(O)>>super.show(O)>>this.show(super(O)) 這里>>super.show(super(O))

System.out.println(b.show(d));   // ⑨ AD,因為A定義了show(D obj),優(yōu)先級為super.show(O)
//相當于this.show(O)>>super.show(O)這里>>this.show(super(O)) >>super.show(super(O))

總結(jié)

對于A a=new B();這種形式的多態(tài),B是A的子類,那么調(diào)用a.func(D obj)時,需要注意這樣幾個問題:
1.func函數(shù)在A未定義、在B定義。會編譯錯誤,因為a的函數(shù)僅限于A定義過的,B的函數(shù)在a中不能訪問
2.func函數(shù)在A、B都有定義。這時應(yīng)采用B的實現(xiàn)。
3.func函數(shù)在A定義,在B未定義。這時會采用A的實現(xiàn)。
4.func函數(shù)在A、B均未定義。會編譯錯誤。
5.func函數(shù)在A、B都有定義,但是func的參數(shù)沒有D,只有D的父類C,那么需要按照this.show(super(O)) >>super.show(super(O))的順序去選擇函數(shù)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • importUIKit classViewController:UITabBarController{ enumD...
    明哥_Young閱讀 4,194評論 1 10
  • SwiftDay011.MySwiftimport UIKitprintln("Hello Swift!")var...
    smile麗語閱讀 4,104評論 0 6
  • 進入預產(chǎn)期月,需要每周產(chǎn)檢一次了。 今天孕36+,按醫(yī)生安排做了B超和胎心監(jiān)護及常規(guī)檢查。 晚上回到家吃過飯也沒有...
    喵喵司令閱讀 358評論 0 0
  • 今天一整天,心情特別平靜,當我意識到金錢在我生命中不是最重要的時候,生命,健康,家庭顯得那么尊貴,感覺自己又是那么...
    斯拓之海閱讀 232評論 0 0
  • 每次海上航行都會帶本書,作為領(lǐng)隊總是住在內(nèi)艙,晨昏只在手表上顯示,所以在船上的時間大都是昏天黑地的睡覺,從來沒認真...
    晨純_0944閱讀 571評論 0 2

友情鏈接更多精彩內(nèi)容