在 Groovy 中克隆和扩展 class
Cloning and extending class in Groovy
我正在尝试在 Groovy 中动态生成 classes。我的做法是:
class MetaClassTest {
static class TestClass {
String getName() {
return "Jake"
}
}
public static void main(String[] args) {
def testClass = TestClass
def metaMethod = testClass.metaClass.getMetaMethod('getName', [] as Class[])
testClass.metaClass.getName = {
metaMethod.invoke(delegate) + " and the Fatman"
}
assert testClass.newInstance().name == "Jake and the Fatman"
}
}
然而,这改变了原始 class 的行为,这是我不想要的。所以我的问题是:
如何动态克隆(并可能重命名)现有的 class 以便我能够创建多个派生对象?
我不确定以下是否有效,但可能值得一试:你能检查一下你是否能以某种方式深度复制 TestClass,然后修改唯一的克隆 class?以下内容可能会派上用场:
也许 groovy lang metaprogramming 可以查找有关元编程的更多信息。
您可以覆盖 class 个实例方法:
import groovy.transform.AutoClone
@AutoClone
class TestClass {
String getName() {
return "Jake"
}
}
def tc1 = new TestClass()
def tc2 = tc1.clone()
tc1.metaClass.getName = {'Fatman'}
tc2.metaClass.getName = {'Joe'}
assert tc1.getName() == 'Fatman'
assert tc2.getName() == 'Joe'
assert new TestClass().getName() == 'Jake'
到目前为止最透明(尽管仍然很脏)的解决方案已经在这里暗示了。我可以使用 GroovyClassLoader.parse()
方法创建子 class 骨架,然后通过 metaClass
.
丰富它
class TestClass {
String getName() {
return "Jake"
}
}
def parentClass = TestClass
def groovyClassLoader = new GroovyClassLoader(parentClass.classLoader)
def childClass1 = groovyClassLoader.parseClass("class ChildClass1 extends ${ parentClass.canonicalName } {}")
def oldGetName1 = childClass1.metaClass.getMetaMethod('getName', [] as Class[])
childClass1.metaClass.getName = {
oldGetName1.invoke(delegate) + " and the Fatman"
}
def childClass2 = groovyClassLoader.parseClass("class ChildClass2 extends ${ parentClass.canonicalName } {}")
def oldGetName2 = childClass2.metaClass.getMetaMethod('getName', [] as Class[])
childClass2.metaClass.getName = {
oldGetName2.invoke(delegate) + " the Dog"
}
assert childClass1.newInstance().name == "Jake and the Fatman"
assert childClass2.newInstance().name == "Jake the Dog"
我在运行时动态创建 classes 的原因是可以使用 Groovy 通常几乎没有任何编程技能的人编写的 DSL 脚本来扩展应用程序。
我正在尝试在 Groovy 中动态生成 classes。我的做法是:
class MetaClassTest {
static class TestClass {
String getName() {
return "Jake"
}
}
public static void main(String[] args) {
def testClass = TestClass
def metaMethod = testClass.metaClass.getMetaMethod('getName', [] as Class[])
testClass.metaClass.getName = {
metaMethod.invoke(delegate) + " and the Fatman"
}
assert testClass.newInstance().name == "Jake and the Fatman"
}
}
然而,这改变了原始 class 的行为,这是我不想要的。所以我的问题是:
如何动态克隆(并可能重命名)现有的 class 以便我能够创建多个派生对象?
我不确定以下是否有效,但可能值得一试:你能检查一下你是否能以某种方式深度复制 TestClass,然后修改唯一的克隆 class?以下内容可能会派上用场:
也许 groovy lang metaprogramming 可以查找有关元编程的更多信息。
您可以覆盖 class 个实例方法:
import groovy.transform.AutoClone
@AutoClone
class TestClass {
String getName() {
return "Jake"
}
}
def tc1 = new TestClass()
def tc2 = tc1.clone()
tc1.metaClass.getName = {'Fatman'}
tc2.metaClass.getName = {'Joe'}
assert tc1.getName() == 'Fatman'
assert tc2.getName() == 'Joe'
assert new TestClass().getName() == 'Jake'
到目前为止最透明(尽管仍然很脏)的解决方案已经在这里暗示了。我可以使用 GroovyClassLoader.parse()
方法创建子 class 骨架,然后通过 metaClass
.
class TestClass {
String getName() {
return "Jake"
}
}
def parentClass = TestClass
def groovyClassLoader = new GroovyClassLoader(parentClass.classLoader)
def childClass1 = groovyClassLoader.parseClass("class ChildClass1 extends ${ parentClass.canonicalName } {}")
def oldGetName1 = childClass1.metaClass.getMetaMethod('getName', [] as Class[])
childClass1.metaClass.getName = {
oldGetName1.invoke(delegate) + " and the Fatman"
}
def childClass2 = groovyClassLoader.parseClass("class ChildClass2 extends ${ parentClass.canonicalName } {}")
def oldGetName2 = childClass2.metaClass.getMetaMethod('getName', [] as Class[])
childClass2.metaClass.getName = {
oldGetName2.invoke(delegate) + " the Dog"
}
assert childClass1.newInstance().name == "Jake and the Fatman"
assert childClass2.newInstance().name == "Jake the Dog"
我在运行时动态创建 classes 的原因是可以使用 Groovy 通常几乎没有任何编程技能的人编写的 DSL 脚本来扩展应用程序。