2017-04-14 89 views
3

我在看this答案,我不明白爲什麼方法是多態而不是字段的邏輯。爲什麼Java字段不是多態?

默認情況下,所有成員函數在Java中都是多態的。這意味着當您調用this.toString()時, Java使用動態綁定來解析調用 調用的子版本。當您訪問成員x時, 訪問當前作用域的成員(父親),因爲成員 不是多態。

當你在超和子類都有些領域x,並在子類中覆蓋toString,當你調用基類中的以下內容:

System.out.println(this); //calls the subclass's toString implementation 
System.out.println(this.x) //prints the base class's x field 

的答案的理由爲這在開始鏈接的問題中列出的是基類在它自己的範圍內不知道子類,但是對於多態,它是同樣的事情:超類不知道子類是否存在,但是子類方法仍然被調用。那麼,Java究竟做了什麼,使得兩者的行爲有所不同 - 一種是在子類中使用動態綁定,另一種是保持超類的作用域?

編輯:爲了澄清,我堅持爲什麼this.x會做與多態性相同的事情,查看對象的實際類型,而不僅僅是參考類型,並打印子類中的x字段。

+1

「類成員」是指「字段」?如果是這樣,那麼說得更清楚些。方法是「成員」以及... –

+0

@JonSkeet,是的,謝謝。我解決了。 – rb612

+0

但由於訪問器是多態的,如果使用getter,則可以實現所需的行爲。 –

回答

1

要實現子類型多態性Java需要跟蹤要調用的方法,它需要額外的開銷。你可以通過保持字段的私密性和使用getter來實現「多態字段」(前者不是必需的,但明智的做法)。你可能有興趣在檢查出

  • invokedynamic
  • invokeinterface
  • invokespecial
  • invokestatic
  • invokevirtual

電話。您可以在這裏閱讀更多關於它的信息: https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.invokevirtual

+0

謝謝!我更好奇爲什麼方法是多態而不是字段。 – rb612

+0

我想我應該強調*需要額外的開銷* :)。讓我們從顛倒你的問題開始:爲什麼訪問字段需要多態機制?對於方法來說,可以通過聲稱子類型多態是OOP世界中功能擴展的基本機制之一來證明其合理性。所以讓我們爲非私有方法添加invokevirtual(與默認值不同)的功能(只是訪問當前對象的方法),並在調用此類方法時接受開銷。我們是否應該接受每次現場解析的開銷,而在需要時可以設置一些設置者/獲取者? –

相關問題