#groovy #metaprogramming
#groovy #метапрограммирование
Вопрос:
У меня возникли проблемы с поиском хорошего способа приведения класса к любому другому классу.
Я использую groovy и пытаюсь заменить стороннюю библиотеку серией no-ops, чтобы предоставить ей функциональность для пробного запуска.
Допустим, у меня есть такой скрипт:
class NoOp {
List tree = []
NoOp(List tree=[]){
this.tree = tree
}
def invokeMethod(String name, Object args) {
return new NoOp(tree name)
}
}
class BigList {
List getNewBigList(){
return ['hello'] // I normally return a lot of stuff
}
}
BigList.metaClass['getNewBigList']={->return new NoOp()}
List list = new BigList().getNewBigList()
// Each function should have a new instance of the NoOp class, causing the next to do nothing
list.iterator().collect{String x->
return x // Marshall Data
}.each{
// Do more stuff here
}
String a = list[0] // Should return a NoOp here
// Remove metaClass from new instances
GroovySystem.metaClassRegistry.removeMetaClass(BigList.class)
Теоретически это работает нормально (и работает до тех пор, пока groovy не попытается привести результат), invokeMethod вернет новый класс NoOp в возвращаемую функцию и приведет к тому, что все последующие использования также ничего не сделают.
Проблема сводится к кастингу. Как только List l = new NoOp()
это произойдет, groovy выдаст ошибку.
Есть ли хороший способ разрешить приведение NoOp к любому типу?
Примечание: это всего лишь фиктивный скрипт, может быть любое количество классов и пакетов, которые будут перезаписаны метаклассом NoOp, поэтому выполнение этого вручную было бы невозможно.
Комментарии:
1. Всего несколько советов: вы изучали переопределение
def asType(Class c)
для решения своей проблемы? Если вы хотите переопределить большое разнообразие, я бы также рассмотрел возможность использования макетных библиотек (они обычно используются для тестов как автоматически сгенерированные резервные модули и могут быть просто тем, что вам нужно здесь)?2. Да, asType не подходит для этого, во-первых, он требует использования ‘as’, иначе он не будет работать с неявными преобразованиями. Во-вторых, кастинг в целом требует, чтобы вы изменили тип данных на новый формат. Например, в строке для перечисления в качестве типа я мог бы сделать что-то вроде.
return "string".split('')
Что касается макетов, я сомневаюсь, что они будут работать по мере необходимости. Я действительно пытаюсь привести к любому классу, который может появиться в цепочке функций. Это могут быть классы Reader / Writer / Model / Support / Helper