2012-11-23 26 views
2

我想在Groovy中使用@Mixin註釋,它完全符合我的需求,除了它也混合私有方法和字段。尋找解決方案Groovy @Mixin不要破壞封裝

class A { 
def private fooA() { 
     println("A") 
    } 
} 

@Mixin(A) 
class B { 
    def fooB() { 
     println("B") 
    } 
} 

如果我現在運行這段代碼

static main(args) 
{ 
    def b = new B() 
    println(b.fooA()) 
    B.metaClass.fooA = {throw new MissingMethodException()}; 
    println(b.fooA()) 
} 

它首先調用私有方法A.fooA並打印 「A」。然後,該私有方法被刪除,不能被類A中混合的客戶類B調用。這是我希望事情從一開始的方式。

我的問題是現在如何以通用的方式實現這一點?我可以擴展@Mixin註釋。問題是我對Groovy很陌生,實際上找不到有關如何編寫AST轉換的信息。新的Groovy in Action書中有一整章關於它的內容還沒有出來。

我可以使用@Delegate來代替,但是我必須爲委託給它的類聲明一個變量。這不是我想要的。我更喜歡我可以告訴開發者使用我的東西來簡單地用@Mixin註釋他的類,以便混合我的東西,就是這樣。我可以肯定,我的班級的私人方法和領域不能由用戶打破混合類的內部代碼調用。

有沒有人有什麼方向的提示,我應該嘗試做到這一點? 謝謝,奧利弗

回答

2

我認爲你已經擊中了一些不是Groovy強烈關注的東西。一般隱藏私人成員的支持有issues

在您的具體情況中,您可能發生了新的錯誤(?)。扯開,它看起來像@Mixin的AST變換調用代碼達到MixinInMetaClass.mixinClassesToMetaClass()。這是努力不要將非公開方法複製到目標元類(B類的目標元類);它們不會顯示在b.metaClass的方法列表中,因此看起來正確。

調用b.fooA()將工作(以某種方式),直到您嘗試使用不存在的屬性或在b上調用一個不存在的方法。 (或致電b.metaClass.initialize())。然後你會收到投訴失蹤fooA()。因此,我不確定我是否會花太多精力嘗試使用訪問修飾符來處理Groovy,但是如果你保持這種路徑,我認爲你可能不得不爲類編寫一些初始化代碼,做一些像你上面所做的事情,或者撥打initialize()或一個不好的屬性,正如我上面提到的。您可以嘗試將這些代碼放在您自己的ASTTransformation類中,但我沒有嘗試過。你可以抓住source並看看org.codehaus.groovy.ast.MixinASTTransformation

+0

嗨,布賴恩,謝謝你的回答。那麼,在輸入「f」後在IDE(我使用IDEA)中彈出自動完成選擇列表。私有方法fooA未列爲可選選項(但是fooB是)。任何仍然在B實例上調用fooA的開發者之前都有過警告。也許這很好。最後,我太習慣於以前的「一切安全」的世界;-)。 – OlliP