Groovy元类替换超类方法。

6
有没有一种方法可以用元类对象来替换超类中的方法。 例如:
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!
 */
1个回答

7

由于twodoIt在同一个类中声明,因此groovy将跳过元对象协议进行此调用。 您可以通过将超类标记为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!

好的...问题在于我只想在 Grails 应用程序中的单元测试中实现这种行为...有没有一种不需要让 A 类实现 GroovyInterceptable 接口就能实现相同效果的方法? - rascio
另一种选择是让B覆盖doIt并自己调用two。或者创建一个测试特定的B子类,使用标准多态性覆盖two而不是元类。 - ataylor
很抱歉,例子和我的情况不一样...我有一个名为BaseService的类,其中有一个方法'getFileOutputStream'用于检索文件输出流并创建文件,在测试期间,我想覆盖它并执行一个存根方法,返回一个ByteArrayOutputStream...所以我有一个调用了两次自身的子类(B),现在我已经将_two_声明为闭包而不是方法来解决它,但我更喜欢将其声明为方法。 - rascio

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接