Конвертировать карту Groovy, реализуя интерфейс обратно на карту - PullRequest
3 голосов
/ 28 февраля 2012

При использовании карты замыканий для реализации интерфейса в Groovy (как в http://groovy.codehaus.org/Groovy+way+to+implement+interfaces) есть ли способ преобразовать объект обратно в карту после использования ключевого слова as или метода asType для реализации интерфейса?

Ответы [ 2 ]

6 голосов
/ 01 марта 2012

Исходя из вашего варианта использования, может показаться, что вы можете просто сохранить ссылку на исходный Map перед преобразованием его в нужный интерфейс.

Однако, глядя на исходный код, который преобразует объект Map в интерфейс (используя Proxy), похоже, что вы можете просто восстановить исходную карту, получив делегат InvocationHandler.

def i = 1
def m = [ hasNext:{ true }, next:{ i++ } ]
Iterator iter = m as Iterator

def d = java.lang.reflect.Proxy.getInvocationHandler(iter).delegate
assert d.is(m)

Примечание: это зависит от внутренних частей кода Groovy, поэтому используйте на свой страх и риск:

2 голосов
/ 28 февраля 2012

Интересный вопрос ... Короткого ответа нет.Длинный ответ, может быть ... Если предположить, что у вас есть что-то вроде этого:

def i = 1
Iterator iter = [ hasNext:{ true }, next:{ i++ } ] as Iterator

, затем звоните

println iter.take( 3 ).collect()

печатает [1,2,3]

Теперь вы можете объявитьметод для этого:

def mapFromInterface( Object o, Class... clz ) {
  // Get a Set of all methods across the array of classes clz
  Set methods = clz*.methods.flatten()
  // Then, for each of these
  methods.collectEntries {
    // create a map entry with the name of the method as the key
    // and a closure which invokes the method as a value
    [ (it.name): { Object... args ->
                   o.metaClass.pickMethod( it.name, it.parameterTypes ).invoke( o, args )
    } ]
  }
}

Затем вы можете сделать:

def map = mapFromInterface( iter, Iterator )

И вызов:

println map.next()
println map.next()

Напечатает 4, а затем 5

печать карты с помощью println map дает:

[ remove:ConsoleScript43$_mapFromInterface_closure3_closure4@57752bea,
  hasNext:ConsoleScript43$_mapFromInterface_closure3_closure4@4d963c81,
  next:ConsoleScript43$_mapFromInterface_closure3_closure4@425e60f2 ]

Однако , поскольку это карта, любой класс, который содержит несколько методов с одинаковым именеми разные аргументы потерпят неудачу.Я также не уверен, насколько разумно делать это в первом случае ...

Чем интересен ваш вариант использования?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...