2012-05-07 52 views
4

有沒有一種方法可以使用元類對象,這是一個超類的方法進行替換。 實施例:groovy metaclass替換超類方法

class A { 
    def doIt(){ 
     two() 
     println 'do it!' 
    } 
    protected two(){ 
     println 'two' 
    } 
} 

class B extends A{ 
    def doLast(){ 
     doIt() 
    } 
} 

B b = new B(); 
b.doIt() 
/* 
* two 
* doit! 
*/ 
b.metaClass.two = { 
    println 'my new two!' 
} 
b.doIt(); 
/* 
* my new two! 
* do it! 
*/ 

回答

7

由於twodoIt在同一類中被聲明,常規將跳過該呼叫的元對象協議。您可以通過將超類標記爲GroovyInterceptable來覆蓋此行爲,這會強制全部方法調用通過invokeMethod。例如:

class A implements GroovyInterceptable { 
    def doIt(){ 
     two() 
     println 'do it!' 
    } 
    protected two(){ 
     println 'two' 
    } 
} 

class B extends A { 
    def doLast(){ 
     doIt() 
    } 
} 

B b = new B() 
b.doIt() // prints two 
b.metaClass.two = { 
    println 'my new two!' 
} 
b.doIt() // prints my new two! 
+0

嗯確定...問題是,我想這種行爲只是爲了在Grails應用程序單元測試...有沒有辦法做到不使A類實現GroovyInterceptable一樣嗎? – rascio

+0

另一種方法是讓B重寫'doIt'並自己調用'two'。或者創建一個B測試特定的子類,用標準多態而不是元類覆蓋'two'。 – ataylor

+0

mmm對不起,這個例子是不一樣的情況,我有...我有一個類BaseService與方法'getFileOutputStream',檢索一個文件輸出流並創建一個文件,在測試期間,我想覆蓋它並做一個存根方法返回一個ByteArrayOutputStream ...所以我有調用_two_本身的子類(B),現在我已經聲明_two_作爲閉包而不是方法,但我寧願將其聲明爲方法 – rascio

相關問題