克隆和扩展Groovy中的类

时间:2018-01-12 09:40:32

标签: java groovy reflection metaprogramming metaclass

我正在尝试在Groovy中动态生成类。我的方法是:

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"
    }
}

然而,这改变了原始类的行为,这是我不想要的。所以我的问题是:

如何动态克隆(并可能重命名)现有类,以便我能够创建多个派生?

3 个答案:

答案 0 :(得分:1)

您可以覆盖类实例方法:

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="72dp"
        android:height="66dp"
        android:viewportHeight="66"
        android:viewportWidth="72">

    <path
        android:fillColor="@android:color/transparent"
        android:pathData="M 0.00 0.00 L 72.00 0.00 L 72.00 66.00 L 0.00 66.00 L 0.00 0.00 Z" />
    <path
        android:fillColor="#F7592B"
        android:pathData="M 20.99 1.04 C 26.30 1.45 30.97 4.88 36.04 5.70 C 40.02 5.23 43.79 2.79 47.70
        1.80 C 56.08 -0.90 65.46 4.21 69.03 11.97 C 71.67 17.65 71.59 24.74 70.62 30.81
        C 68.57 41.48 60.32 50.55 51.81 56.81 C 47.69 59.73 43.11 62.72 38.21 64.12 C
        34.80 65.13 31.23 63.34 28.24 61.86 C 19.69 57.27 11.77 50.76 6.25 42.72 C 0.82
        34.78 -0.33 24.87 1.66 15.60 C 3.69 7.15 12.14 0.18 20.99 1.04 Z" />
    <path
        android:fillColor="#1721dc"
        android:pathData="M 19.98 7.14 C 25.68 7.39 30.87 12.07 36.10 12.99 C 41.30 12.15 46.97 7.14 52.84
        7.35 C 58.72 7.85 63.41 12.52 64.67 18.17 C 65.71 23.40 65.21 29.32 63.25 34.30
        C 59.83 42.88 52.20 49.81 44.38 54.43 C 40.52 56.53 36.81 58.58 32.37 56.70 C
        24.56 53.51 17.02 47.75 12.20 40.77 C 7.31 33.87 5.58 24.79 7.64 16.59 C 9.15
        11.09 14.21 6.98 19.98 7.14 Z" />
</vector>

答案 1 :(得分:0)

我不确定以下是否有效,但可能值得一试:你能检查一下你是否可以以某种方式深度复制TestClass,然后修改唯一的克隆类?以下可能会派上用场:

使用autoclone

也许groovy lang metaprogramming可以在元编程上寻找更多信息。

答案 2 :(得分:0)

到目前为止,最透明(尽管仍然很脏)的解决方案已在此处暗示过。我可以使用GroovyClassLoader.parse()方法创建子类骨架,然后通过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"

我在运行时动态创建类的原因是,应用程序可以使用Groovy DSL脚本进行扩展,这些脚本通常由几乎没有任何编程技能的人编写。