使用Groovy metaClass实现特殊方法

时间:2017-06-15 21:35:34

标签: groovy dynamic-programming metaclass expandometaclass

我正在尝试在Groovy中修改JSONObject的元类,使其尽可能像常规的Groovy映射一样运行。当我在元类中实现方法时,其中一些方法很简单,如下例中的JSONObject.metaClass.size。 JSONObject有一个length()方法,我只是将它连接到一个新的size()方法,但有些方法有特殊含义。例如,要使下标赋值起作用,我必须覆盖propertyMissing,而不是putAt。看起来很像像each,collect,findAll等很多集合操作都是类似的。

我的第一个问题是在这种情况下我需要覆盖哪些特殊方法才能使每个()工作?我的第二个问题是我如何自己找出答案?是否有某些参考方法可以从MOP获得特殊待遇?我试着查看groovy-core源代码,但那里有很多,我不知道从哪里开始。

node

1 个答案:

答案 0 :(得分:3)

@Grab(group='org.json', module='json', version='20160810')

import org.json.JSONArray
import org.json.JSONObject

JSONObject.metaClass.each={Closure c-> 
    delegate.keys().each{ k-> c(k, delegate.get(k) ) }  
}

JSONObject.metaClass.setProperty={String k, Object v-> 
    delegate.put(k,v) 
}

JSONObject.metaClass.getProperty={String k-> 
    delegate.get(k) 
}

JSONObject.metaClass.size = { -> delegate.length() }

def json = new JSONObject()
json['a'] = 999
json.b    = 2.2
json['c'] = 'the letter C'
println json['a']            // Prints 999
println json['b']            // Prints 2.2
println json.c               // 'the letter C'
println json.size()         // Prints 3

//No signature of method: ... $__spock_feature_0_0_closure4.doCall() is applicable 
json.each{ k,v -> println "$k = $v"}

输出:

999
2.2
the letter C
3
a = 999
b = 2.2
c = the letter C