Есть ли способ сделать класс кастомным для любого объекта?

#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