groovy MetaClass 剖析 1

<!----><!---->

本篇介绍groovy 的MetaClasses ,MetaClass 是Groovy 动态编程比较重要的组成。

(以下出现的代码片段是在groovy1.5.3测试通过,希望各位可以运行之)。

 

1.MetaClass

           groovy中出现的每个类都有其对应的MetaClass。MetaClas是一个接口,该接口扩展了MetaObjectProtocol接口,这就是我们通常所说的MOP协议了。

MetaClass的实现类主要有 

 

 

MetaClassImpl 是通用的实现类。ClosureMetaClass是闭包类特有的MetaClass。ExpandoMetaClass是用户扩展groovy类行为时用到的MetaClass

 

println 'first:---> '+'test'.metaClass

println 'String.metaClass:---> '+String.metaClass

println 'after String.metaClass:--->  '+'test'.metaClass

 

执行结果为
first:---> groovy.lang.MetaClassImpl@183f74d[class java.lang.String]
String.metaClass:---> groovy.lang.ExpandoMetaClass@8a0d5d[class java.lang.String]
after String.metaClass:--->  groovy.lang.ExpandoMetaClass@8a0d5d[class java.lang.String]

 对于这样的结果你是不是会感觉到奇怪呢?

下面我将结合Groovy实现代码来解释这个过程

第一句脚本 通过String实例对象来获得,Groovy为其初始化的groovy.lang.MetaClassImpl@183f74d[class java.lang.String]对象。这个对象将在MetaClassRegistryImpl中和String类关联起来。也就是注册了String.class和

groovy.lang.MetaClassImpl的对象关系。

第二句脚本 通过String类去访问 metaClass对象,不过这一次是调用了类DefaultGroovyMethods中的方法

 

    /**
     * Adds a "metaClass" property to all class objects so you can use the syntax
     * <code>String.metaClass.myMethod = { println "foo" }</code>
     *
     * @param c The java.lang.Class instance
     * @return An MetaClass instance
     */
    public static MetaClass getMetaClass(Class c) {
        MetaClassRegistry metaClassRegistry = GroovySystem.getMetaClassRegistry();
        MetaClass mc = metaClassRegistry.getMetaClass(c);
        if (mc instanceof ExpandoMetaClass
                || mc instanceof DelegatingMetaClass && ((DelegatingMetaClass) mc).getAdaptee() instanceof ExpandoMetaClass)
            return mc;
        else {
            MetaClass emc = ExpandoMetaClassCreationHandle.instance.create(c, metaClassRegistry);
            emc.initialize();
            metaClassRegistry.setMetaClass(c, emc);//并且在metaClassRegistry中注册
            return emc;
        }
    }

 第三句脚本又重新通过String实例对象来获得了,但这一次得到的是groovy.lang.ExpandoMetaClass@8a0d5d,这是因为第二句话中对String和其MetaClass对象进行了重新注册。

自此以后系统中所有的String对象的MetaClass对象都一直市是ExpandoMetaClass对象实例。

 

 

由于我们举的String例子有点特殊

我们看看对于自定义类的例子

class Foo{
	
}
def f1 = new Foo();
println f1.metaClass

println Foo.metaClass

println f1.metaClass

def f2 = new Foo()
println f2.metaClass

 结果是不是又不一样了?

f1对象的metaClass是被缓存了,只有在调用过

Foo.metaClass

 之后,new出来的对象才会使用ExpandoMetaClass

 

 

你可能感兴趣的:(C++,c,脚本,C#,groovy)