Groovy 将代码添加到构造函数
Posted
技术标签:
【中文标题】Groovy 将代码添加到构造函数【英文标题】:Groovy adding code to a constructor 【发布时间】:2011-08-19 22:18:31 【问题描述】:Groovy 中是否有一种方法可以在实例化类时向构造函数添加代码?我有一个 Groovy 类(但我不能修改这个特定类的源代码),但我希望有一种方法可以注入代码(可能通过元类),这样我的代码就会作为构造函数的一部分运行(在这个如果只有一个,默认构造函数)。
谢谢, 杰夫
【问题讨论】:
我自己从来没有这样做过,但这可能会有所帮助groovy.codehaus.org/ExpandoMetaClass+-+Constructors 【参考方案1】:您可以覆盖构造函数,但这有点棘手,尤其是在覆盖默认构造函数时。您需要为类的metaClass.constructor
分配一个闭包,并且该闭包应该返回一个新实例。棘手的部分是,如果您调用已覆盖的构造函数,您将进入递归循环并生成堆栈溢出。您需要另一种方法来获取类的实例,例如不同的构造函数。
对于测试,有时可以绕过此限制。通常,首先实例化一个对象,然后重写构造函数以返回现有实例就足够了。示例:
class MyObject
String something
MyObject() something = "initialized"
testInstance = new MyObject()
testInstance.something = "overriden"
MyObject.metaClass.constructor = -> testInstance
aNewObject = new MyObject()
assert aNewObject.is(testInstance)
assert aNewObject.something == "overriden"
【讨论】:
我想我应该能够使用 2 个构造函数来完成我需要完成的事情。谢谢。【参考方案2】:可以添加新的构造函数或替换旧的构造函数。如果您需要原始构造函数,则可以使用反射:
MyObject.metaClass.constructor = -> // for the no-arg ctor
// use reflection to get the original constructor
def constructor = MyObject.class.getConstructor()
// create the new instance
def instance = constructor.newInstance()
// ... do some further stuff with the instance ...
println "Created $instance"
instance
请注意,如果您的构造函数有参数,则必须更改此设置,例如:
// Note that the closure contains the signature of the constructor
MyObject.metaClass.constructor = int year, String reason ->
def constructor = MyObject.class.getConstructor(Integer.TYPE, String.class)
def instance = constructor.newInstance(
2014, "Boy, am I really answering a question three years old?")
// ... do some further stuff with the instance ...
println "Created $instance"
instance
PS:请注意,当您要添加尚不存在的构造函数时,请改用<<
运算符:MyObject.metaClass.constructor << /* as above */
。
【讨论】:
【参考方案3】:您可以通过使用标准 Java 反射存储原始构造函数来绕过建议的解决方案中的限制。例如,这是我在 spock 测试中初始化一个类(基本注入):
def setupSpec()
MockPlexusContainer mockPlexusContainer = new MockPlexusContainer()
def oldConstructor = MY_CLASS.constructors[0]
MY_CLASS.metaClass.constructor = ->
def mojo = oldConstructor.newInstance()
mockPlexusContainer.initializeContext(mojo)
return mojo
这只会被调用一次,但每次有人调用构造函数时,我都会得到一个不同的实例,从而避免清理值并确保线程安全。
【讨论】:
以上是关于Groovy 将代码添加到构造函数的主要内容,如果未能解决你的问题,请参考以下文章
GroovyGroovy 方法调用 ( Groovy 构造函数中为成员赋值 | Groovy 函数的参数传递与键值对参数 | 完整代码示例 )
重写构造函数中调用的方法时,Groovy metaClass 失败?
Groovy循环控制 ( Java 语法循环 | 默认的 IntRange 构造函数 | 可设置翻转属性的 IntRange 构造函数 | 可设置是否包含 to 的构造函数 | 0..9 简写 )(代