簡體   English   中英

為什么在編譯時確定方法重載決議?

[英]Why is method overload resolution determined at compile time?

我試圖理解為什么我們有具有覆蓋方法的多態性/動態綁定,但沒有重載方法。 我知道有間接性允許我們索引到一個 vtable 中,從而允許我們用 C++ 或 Java 之類的語言來做到這一點。 我很好奇為什么解決重載方法的情況並非如此——我的直覺讓我相信我們可以有一個間接級別,允許我們在運行時確定基於運行時類型調用哪個重載方法。

我想知道這個設計決定是出於性能原因還是我忽略了額外的復雜性。

我沒有讀過語言設計者的心思,所以不能真正告訴你。 我是這樣想的:

  • 重寫方法是同一方法在超類/子類層次結構中的不同級別的不同實現。 子類一般使用相同的方法簽名(允許返回更具體的類型並聲明更少的異常拋出,但不能完全重新定義方法頭,否則將不再是覆蓋)。
  • 重載方法實際上只是碰巧具有相同名稱的不同方法。 然后使用參數類型進行區分。 就像編譯器總是在編譯時決定調用哪個方法一樣,重載方法也是如此。

作為一個觀察(可能是次要的),對於重載方法的運行時解析,我們不能再靜態地對返回值進行類型檢查。 想象一下我們有

public boolean foo(Number n);
public String foo(Integer i);

現在我會發現像這樣調用前一個foo()是很自然的:

    boolean result = foo(myNumber);

現在,如果myNumber碰巧是一個Integer ,則將調用后者foo() 它會返回一個String ,我會在運行時發生類型轉換錯誤。 我不會感到驚訝。

... 為什么那么我們仍然可以擁有運行時多態性並且它被認為是靜態類型,但是如果我們對重載方法進行動態解析就不會了。

Java 有兩種類型:靜態類型和運行時類型。 當我將一個Integer存儲到一個聲明為Number的變量中時, Number是靜態類型, Integer是運行時類型(順便說一句,類型與類不同)。 你是對的,當我做myObject.foo(arg)時, myObject的運行時類型決定調用foo()哪個實現。 並且可以想象, arg的運行時類型也可能參與決策。 它會變得更復雜,我不確定收益。

重載方法是具有相同名稱但采用不同參數的方法。 您可以簡單地將其采用的參數的類型和順序(以及它返回的值的類型)作為名稱的一部分。

在 C++ 中,這實際上更“暴露” - 這種語言在內部調整名稱以匹配參數, void h(int, char)變得類似於h__Ficvoid h(int)類似於h__Fi 這些被破壞的名稱偶爾會出現在諸如有關它們未解析的錯誤消息之類的地方。 在 Java 中,這較少暴露,但在內部具有可比性。 這也稱為“簽名”。

然后您的問題簡化為“如果方法具有不同的名稱,為什么它們在編譯時而不是運行時被解析?”。 具有不同簽名的兩種方法之間的分辨率不會隨着時間的推移而改變,因此延遲它根本沒有理由也沒有好處。

暫無
暫無

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

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