[英]Determining which overrides method is actually invoked
例如,將子類對象強制轉換為其超類時
Superclass obj = new Subclass();
並且定義了類
public class Superclass{
public void thisMethod(){
System.out.println("Superclass version was executed");
}
和
public class Subclass extends Superclass{
public void thisMethod(){
System.out.println("Subclass version was called");
}
public void newMethod(){
System.out.println("blah");
}
}
當obj.thisMethod()
時,我得到Subclass version was called
作為輸出,這顯然意味着該方法的版本在子類中定義(原始超類對象無法“執行”的版本),盡管聲明的類型是超類,是嗎? 因此,即使子類方法是在obj上執行的,當obj.newMethod()
時, obj.newMethod()
出現編譯錯誤。
基本上,為什么通過超類對象obj
調用子類中定義的thisMethod()
的版本? 我知道obj
的實際類型仍然是Subclass,因此自然應該調用新版本,但是那我不能調用obj.newMethod()
嗎?
感謝堆的任何解釋(:
編輯:標題中意為覆蓋*
基本上,為什么通過超類對象obj調用子類中定義的thisMethod()的版本?
因為這基本上就是繼承的要點-它允許重寫實現,而調用代碼無需知道正在使用哪個實現。 以InputStream
為例-您可以使用InputStream
進行編碼,然后無論傳遞了FileInputStream
, ByteArrayInputStream
等,相同的代碼都將起作用。在使用抽象類或接口的情況下,您可能正在調用的方法不在編譯時類型中有任何實現-但是可以保證在執行時使用的具體對象類型中有一個實現。
我知道obj的實際類型仍然是Subclass,所以自然應該調用新版本,但是那我不應該能夠調用
obj.newMethod()
嗎?
否,因為obj
的編譯時類型為Superclass
。 區分變量的編譯時類型(確定哪些方法可用)與變量值所引用的對象的執行時間類型(確定實際調用的方法實現)之間的區別非常重要。
那只是一個非常簡短的描述-您應該閱讀一本關於繼承的不錯的Java書,以獲取更多詳細信息。
從理論上講, obj
是指向Subclass
對象的Superclass
引用。
因為編譯器obj
只是一個Superclass
所以可以調用所有Superclass
的方法,例如thisMethod
,編譯器不知道對象的類型,而只是引用的類型,因此編譯器將拒絕newMethod
因為它可以不能證明這種方法存在。
但是在運行時,對象的類型用於分配方法,而不是引用的類型,因此thisMethod
將解析為Subclass
的版本。
現在,如果我們知道運行時對象是Subclass
類型,我們想告訴編譯器,我們進行強制轉換:
Subclass subobj = (Subclass) obj;
之后,編譯器知道subobj
是Subclass
類型,並且將接受調用newMethod
, newMethod
類型newMethod
只是編譯器的信息,並且不會更改對象obj
任何內容,如果obj
不是Subclass
則先前的語句將在以下位置拋出ClassCastException
:運行。
在這個定義中,超類obj = new Subclass()您只能在超類中公開方法,並且在您聲明將實際上調用Subclass對象的聲明時將調用任何方法將調用子類實現
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.