使用 Groovy 元类实现特殊方法
Using Groovy metaClass to Implement Special Methods
我正在尝试修改 Groovy 中 JSONObject 的元类,使其行为尽可能像常规 Groovy 地图。当我在元类中实现方法时,其中一些方法很简单,例如下面示例中的 JSONObject.metaClass.size。 JSONObject 有一个 length() 方法,我只是将它连接到一个新的 size() 方法,但有些方法有特殊含义。例如,要使下标赋值起作用,我必须覆盖 propertyMissing,而不是 putAt。看起来像 each、collect、findAll 等很多集合操作都是相似的。
我的第一个问题是在这种情况下我需要覆盖哪些特殊方法才能使 each() 工作?我的第二个问题是我如何自己找出答案?某处是否有从 MOP 获得特殊待遇的方法的参考?我试着查看 groovy-core 源代码,但里面有很多,我不知道从哪里开始。
JSONObject.metaClass.propertyMissing = { String name, newValue -> delegate.put(name, newValue) }
JSONObject.metaClass.size = { -> delegate.length() }
JSONObject.metaClass.each = { cl -> delegate.keys().collectEntries{ [(it): delegate[it] ]}.each(cl) }
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"}
@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
我正在尝试修改 Groovy 中 JSONObject 的元类,使其行为尽可能像常规 Groovy 地图。当我在元类中实现方法时,其中一些方法很简单,例如下面示例中的 JSONObject.metaClass.size。 JSONObject 有一个 length() 方法,我只是将它连接到一个新的 size() 方法,但有些方法有特殊含义。例如,要使下标赋值起作用,我必须覆盖 propertyMissing,而不是 putAt。看起来像 each、collect、findAll 等很多集合操作都是相似的。
我的第一个问题是在这种情况下我需要覆盖哪些特殊方法才能使 each() 工作?我的第二个问题是我如何自己找出答案?某处是否有从 MOP 获得特殊待遇的方法的参考?我试着查看 groovy-core 源代码,但里面有很多,我不知道从哪里开始。
JSONObject.metaClass.propertyMissing = { String name, newValue -> delegate.put(name, newValue) }
JSONObject.metaClass.size = { -> delegate.length() }
JSONObject.metaClass.each = { cl -> delegate.keys().collectEntries{ [(it): delegate[it] ]}.each(cl) }
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"}
@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