7

Groovy 公开了一个ExpandoMetaClass允许您将实例和类方法/属性动态添加到 POJO 的方法。我想用它来为我的一个 Java 类添加一个实例方法:

public class Fizz {
    // ...etc.
}

Fizz fizz = new Fizz();
fizz.metaClass.doStuff = { String blah -> fizz.buzz(blah) }

这相当于将Fizz类重构为:

public class Fizz {
    // ctors, getters/setters, etc...

    public void doStuff(String blah) {
        buzz(blah);
    }
}

我的问题:

这是否只添加doStuff(String blah)到这个特定的实例Fizz?还是现在的所有实例Fizz都有一个doStuff(String blah)实例方法?

如果是前者,我如何让所有实例Fizz都有doStuff实例方法?我知道如果我制作了 Groovy:

fizz.metaClass.doStuff << { String blah -> fizz.buzz(blah) }

然后将添加一个静态类方法Fizz,例如Fizz.doStuff(String blah),但这不是我想要的。我只希望所有实例Fizz现在都有一个名为doStuff. 想法?

4

1 回答 1

3

首先,当您添加到 Fizz 的主类时,它的实例不会获取方法,因为实例已经被分解并添加到内存中。

所以解决这个问题的一种方法是使用原始类的方法签名。因此,而不是

fizz.doStuff(blah)

调用类的方法。所以

fizz.&doStuff(blah)

这从原始类获取方法签名,但使用实例中的属性。但是,正如您可以想象的那样,由于它调用了原始类,因此这是一个稍微沉重的调用。

现在推出每个实例的一种替代方法是使实例 ExpandoMetaClass 成为 Fizz 的实例。因此...

Fizz.metaClass.doStuff = {return "blah"}
fizz = new Fizz()
Fizz.metaClass.doOtherStuff = {return "more blah"}
assert fizz.doOtherStuff() == "more blah"

希望这可以帮助

更新:

完整代码示例:

class Fizz{
}

Fizz.metaClass.doOtherStuff = {return "more blah"}
def fizz = new Fizz()
assert fizz.doOtherStuff() == "more blah"

def fizz1 = new Fizz()
assert fizz1.doOtherStuff() == "more blah"
于 2013-11-06T20:50:08.267 回答