簡體   English   中英

為什么在使用超類引用調用子類方法時出現編譯時錯誤?

[英]Why do I get a compile-time error when calling a subclass method using superclass reference?

我知道在方法重寫的情況下會發生多態。 但是我對以下內容有些困惑。

class A {
    public void hi() {
        System.out.println("A "+this.getClass().getName()); 
    }
}

class B extends A {
    public void bye() {
        System.out.println("B "+this.getClass().getName());
    }
}

class Ideone {
    public static void main (String[] args) throws java.lang.Exception {
        A a = new B();
        a.hi();
        a.bye();
    }
}

輸出:

Main.java:35: error: cannot find symbol
        a.bye();
         ^
  symbol:   method bye()
  location: variable a of type A
1 error

為什么這會產生編譯時錯誤?

a = new B()B類對象是在運行時創建的,因此a一個指向B類型對象的引用變量。

現在,如果我們調用B的類方法bye() ,為什么它是編譯器錯誤?

a變量可以在運行時包含類的實例A或任何亞類的A 因此,您只能為該變量調用類A方法。

編譯器僅在確定哪些方法調用有效時才關心變量的編譯時類型。

變量a的聲明類型為A。編譯器在運行時不知道(也不應該知道)它的具體類型是B。它所知道的只是它是A,並且沒有bye()方法。在一個。

整個工作要做

A a = new B();

並不是

B a = new B();

明確表示a是A,並且可以有任何具體類型,只要conrete類型擴展了A。如果稍后找到更好的A實現,則必須能夠將該行更改為

A =新的BetterImplementation();

並編譯代碼。

多態性基本上是對象采取多種形式的能力。 由於您的父類引用的是子類對象,因此它是多態的。

Main.java:35: error: cannot find symbol
        a.bye();
         ^
  symbol:   method bye()
  location: variable a of type A
1 error

之所以出現此錯誤,是因為您試圖從超類引用中調用子類的方法。

在這里,您可以將subClass對象ref分配給超類,這很好。 但是超類只能調用它自己的已知方法和數據。

A a = new B();
 a.hi(); // member of super class
 a.bye(); // Not a member a super class

將新的B實例分配給類型A的引用就像使它戴上了僅在A中定義的方法。 那就是您在A處描述的接口。 即使該實例具有bye的實現,您也只能訪問hi

一種簡單的理解方法是A a可能實際上指向B的對象,但是在編譯期間編譯器並不知道這一點。

編譯器僅檢查引用即“ a”,並查看其類(即“ A”)是否具有其引用“ a”正在嘗試調用的方法。

在您的情況下,引用“ a”沒有名為bye()的方法,因此根據編譯器,無法進行此類調用,這就是您看到該錯誤的原因。

我認為您已經從其他答案中得到了多態性問題的答案。 除此之外,您還可以通過類型轉換使代碼以這種方式工作。

(B)a.bye();

是一個很好的解釋,可幫助您閱讀有關引用與對象類型的信息。 是一篇有關鑄造的好文章。

您只能從父類類型訪問父類方法。

A a = new B();

解決方案1:

將父級更改為子級( B b = new B () )並調用B方法。

解決方案2:

檢查父對象是否為子對象的實例。 如果是,則將父項強制轉換為Child並調用該方法。

class Ideone {
    public static void main (String[] args) throws java.lang.Exception {
        A a = new B();
        a.hi();
        if ( a instanceof B){       
            ((B)a).bye();
        }
    }
}

輸出:

A B
B B

看看instanceof上的oracle文檔頁面

instanceof運算符將對象與指定類型進行比較。 您可以使用它來測試對象是實現特定接口的類的實例,子類的實例還是類的實例。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM