簡體   English   中英

與java的繼承相比,Groovy的擴展模塊

[英]Groovy's extension-module compared to java's inheritance

groovy的擴展模塊是java的繼承功能的混合形式嗎? 為什么擴展模塊需要聲明為靜態?

簡短的回答是我想是的。 由於擴展方法的繼承完全由運行時(和靜態編譯器)完成,因此有點難以清楚地回答。 因此,它與Java如何繼承無關。

回答第二個問題......它們是靜態的,因為在你需要狀態的情況下,你通常使用元類。 擴展方法最初被認為是方便方法或使API更加Groovy。 因此,它們是添加到元類的一種特殊形式的方法。 您可以將它們視為簡化版本。 但這也意味着他們沒有所有的能力。 實現擴展方法,可以在每個“自”對象的基礎上保持本地狀態(基本上是什么字段/屬性)實際上很難有效...但是你總是可以使用每個實例元類來實現這一點。

出於所有廣泛的目的,它們是語法糖,因此靜態方法似乎更像OOP。 沒有繼承,因為Java和Groovy中的靜態方法不參與繼承(即類不繼承靜態方法)。

這些方法需要是靜態的,因為編譯器不知道如何實例化擴展方法的周圍類。

但是我相信有些語言允許在封閉類之外定義方法並進行某種類型的繼承但不是很多(我相信CLOS和Dylan都這樣做)。 它們也是許多語言,似乎允許添加方法,但“對象”的類型實際上已更改/隱藏到其他類型。 這稱為adhoc多態(例如Clojure,Haskell,Golang和Scala的類型)但又與包含多態(Java繼承)無關。

不幸的是, 參考文檔和其他文檔沒有定義擴展方法的語義:

  • 問:他們可以覆蓋實例方法嗎?
    我通過use Category方法和metaClass expando方法測試了擴展方法。 這兩種方法都不會覆蓋實例方法。 我沒有測試通過模塊描述符安裝的擴展模塊
  • 問:它們可以被子類的擴展方法覆蓋嗎?
    我也測試過了。 use方法和metaClass擴展方法不會被子類上的擴展方法覆蓋。
  • 問:他們可以調用繼承的super方法嗎?
    不,因為它們是通過static方法實現的。
  • 問:他們可以打電話給私人方法嗎?
    實驗表明,他們可以,令人驚訝。
  • 問:他們可以訪問私有實例變量嗎?
    不,因為它們是通過static方法實現的。
  • 問:它們可以從Java方法調用嗎?
    也許, 如果擴展模塊在編譯調用代碼時位於類路徑上 我沒有測試它。

結論: 擴展方法不是一種繼承形式。 它們似乎是通用函數調用語法(UFCS)的動態形式,也就是說,當語言找不到方法variable.foo(arguments)它會查找要調用的靜態擴展函數foo(variable, arguments) [如果錯誤,請糾正我的假設!]

你問為什么他們被定義為static 這似乎與語義相匹配:一個靜態函數,它不涉及繼承,雖然它的調用語法使它看起來像一個方便的方法調用。

您可以使用@ groovy.lang.Category批注編寫類似實例方法的擴展方法。 這在編譯時進行AST轉換,將其轉換為合適的靜態方法。

另請參閱Groovy特征 (mixin)繼承的一種形式。

暫無
暫無

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

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