[英]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()的方法,因此根據編譯器,無法進行此類調用,這就是您看到該錯誤的原因。
您只能從父類類型訪問父類方法。
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.