【问题标题】:Groovy get metaClass of subtypeGroovy 获取子类型的元类
【发布时间】:2020-07-28 19:42:51
【问题描述】:

我尝试动态地将属性添加到从一个公共类继承的类型的实例中。为了让用户更简单,我想在超类中创建一个辅助方法:

class Super {
    void add(String propertyName, Object value) {
        this.metaClass."$propertyName" = value
    }
}

class X extends Super {
    String name
    int value
}

X a = new X(name: 'a', value: 4)
X b = new X(name: 'b', value: 5)

a.add('other', 5)
b.add('other', 4)

println a​​.other
println b.other​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​

此代码打印:

4
4

但是,如果改为使用“添加”方法,我直接在实例上设置元属性:

a.metaClass.other = 5
b.metaClass.other = 4

println a​​.other
println b.other​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​

打印出来:

5
4

我知道,例如,不仅有一个元类,而且每个层次结构类都有自己的。有没有办法获得子类的元类,或者我完全错过了这个想法?

更新

如果我添加子类:

    {
        super.setMetaClass(metaClass)
    }

它似乎有效,但我宁愿避免它。

我看到子类型 metaClass 看起来像:

org.codehaus.groovy.runtime.HandleMetaClass@25b53784[groovy.lang.ExpandoMetaClass@25b53784[class X]]

和超类型元类:

groovy.lang.ExpandoMetaClass@25b53784[class X]

【问题讨论】:

  • 有趣的是,如果我再添加一个超级类型级别,它就会起作用。我为每种类型打印 metaClass,它们是:groovy.lang.ExpandoMetaClass@142d5d89[class X] org.codehaus.groovy.runtime.HandleMetaClass@142d5d89[groovy.lang.ExpandoMetaClass@142d5d89[class X]] org.codehaus.groovy .runtime.HandleMetaClass@142d5d89[groovy.lang.ExpandoMetaClass@142d5d89[class X]] 所以看起来最高的类是不同的,而不是HandleMetaClass。

标签: groovy metaprogramming


【解决方案1】:

如果你想使用父类metaClass,你需要使用super.metaClass而不是this.metaClass来访问它,如下例所示:

class Super {
    void add(String propertyName, Object value) {
        super.metaClass."$propertyName" = value
    }
}

class X extends Super {
    String name
    int value
}

X a = new X(name: 'a', value: 4)
X b = new X(name: 'b', value: 5)

a.add('other', 5)
b.add('other', 4)

println a.other
println b.other

输出:

$ groovy test.groovy
5
4

或者,您可以使用与this.metaClass 一起正常工作的特征(特征将add 方法添加到实现特征的类中,因此this.metaClass 在该上下文中按预期工作。)

trait Super {
    void add(String propertyName, Object value) {
        this.metaClass."$propertyName" = value
    }
}

class X implements Super {
    String name
    int value
}

X a = new X(name: 'a', value: 4)
X b = new X(name: 'b', value: 5)

a.add('other', 5)
b.add('other', 4)

println a.other
println b.other

【讨论】:

  • 我现在在这里测试:groovyconsole.appspot.com 所以也许有像 ExpandoMetaClass.enableGlobally() set 这样的东西...
  • 是的,就是这样。更新了答案以涵盖类和特征用例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-18
  • 2014-11-28
  • 1970-01-01
相关资源
最近更新 更多