【问题标题】:Groovy Meta-Programming added method is not accessible in subclassGroovy Meta-Programming 添加的方法在子类中不可访问
【发布时间】:2015-11-28 04:52:48
【问题描述】:

我有以下类来扩展 Object 类,但是这里添加的方法不能被任何 Object 的子类访问。是否有解决方法或 Groovy 元编程限制/限制?

package groovy.runtime.metaclass.java.lang;

class ObjectMetaClass extends DelegatingMetaClass {
    static {
        Object.metaClass.enableGlobally();
    }

    ObjectMetaClass(MetaClass meta) {
        super(meta);
        meta.enableGlobally();
    }

    Object invokeMethod(Object object,
                        String method,
                        Object[] arguments) {
        if (method == 'bar') {
            bar(*arguments);
        } else {
            super.invokeMethod object, method, arguments
        }
    }

    Object bar(config, app) {
        println("... ObjectMetaClass.bar(${config}, ${app})");
    }
}

在测试脚本中:

o = new Object();
o.bar("profile.properties", "meta-app"); // works

1.bar("profile.properties", "integer-app"); // does not works
"aString".bar("profile.properties", "string-app"); // does not works

【问题讨论】:

    标签: inheritance groovy metaprogramming


    【解决方案1】:

    您至少有两个选项:ExpandoMetaClassCategories

    使用 ExpandoMetaClass

    Object.metaClass.bar = {config, app ->
        "... Object.bar(${config}, ${app})"
    }
    
    o = new Object();
    
    assert o.bar("profile.properties", "meta-app") == '... Object.bar(profile.properties, meta-app)'
    assert 1.bar("profile.properties", "integer-app") == '... Object.bar(profile.properties, integer-app)'
    assert "aString".bar("profile.properties", "string-app") == '... Object.bar(profile.properties, string-app)'
    

    有一个类别

    class BarCategory {
        static Object bar(Object self, config, app) {
            "... Object.bar(${config}, ${app})"
        }
    }
    
    use(BarCategory) {
        o = new Object();
    
        assert o.bar("profile.properties", "meta-app") == '... Object.bar(profile.properties, meta-app)'
        assert 1.bar("profile.properties", "integer-app") == '... Object.bar(profile.properties, integer-app)'
        assert "aString".bar("profile.properties", "string-app") == '... Object.bar(profile.properties, string-app)'
    }
    
    o = new Object();
    
    try {
        o.bar("profile.properties", "meta-app")
        assert false, 'You should not see this'
    } catch (MissingMethodException) {}
    
    try {
        1.bar("profile.properties", "integer-app")
        assert false, 'You should not see this'
    } catch (MissingMethodException) {}
    
    try {
       "aString".bar("profile.properties", "string-app")
        assert false, 'You should not see this'
    } catch (MissingMethodException) {}
    

    使用类别,您可以控制bar() 方法的范围。

    【讨论】:

    • 有没有办法将 Object.metaClass.bar = { .. } 放在它会自动加载的地方,这样它就不需要出现在每个脚本中?谢谢!类别也是很好的方式,但我尽量减少修改现有脚本的需要。再次感谢
    • 除了类静态初始化器(在你的情况下不起作用)我不知道如何自动加载元编程。我相信有两种方法。目前我找不到一个,但另一个使用自动加载的类别:docs.groovy-lang.org/docs/groovy-latest/html/documentation/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-24
    • 1970-01-01
    • 2013-09-08
    • 2015-11-27
    • 1970-01-01
    • 2013-11-15
    • 1970-01-01
    相关资源
    最近更新 更多