Использование мета-класса Groovy для реализации специальных методов
Я пытаюсь изменить метакласс для JSONObject в Groovy, чтобы он вел себя как можно больше, как обычная карта Groovy. Когда я реализую методы в метаклассе, некоторые из них просты, как JSONObject.metaClass.size в приведенном ниже примере. У JSONObject есть метод length(), и я просто связываю его с новым методом size(), но некоторые методы имеют особое значение. Например, чтобы заставить работать индекс, мне пришлось переопределить свойство Missing, а не putAt. Похоже, что многие операции по сбору, такие как each, collect, findAll и т. Д., Похожи.
Мой первый вопрос: какие специальные методы мне нужно переопределить в этом случае, чтобы каждый () работал? Мой второй вопрос: как бы я сам нашел ответ? Есть ли где-нибудь ссылка на методы, которые получают специальное лечение от СС? Я попытался взглянуть на исходный код 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"}
1 ответ
@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