Лучшая идиома Groovy закрытия, заменяющая внутренние классы Java?

Как новичок в groovy ...

Я пытаюсь заменить java-идиому для прослушивателей событий, фильтров и т. Д.

Мой рабочий код в Groovy следующий:

def find() {
    ODB odb = ODBFactory.open(files.nodupes); // data nucleus object database
    Objects<Prospect> src = odb.getObjects(new QProspect());

    src.each { println it };

    odb.close();

}

class QProspect extends SimpleNativeQuery {
    public boolean match(Prospect p) {
        if (p.url) {
            return p.url.endsWith(".biz");
        }
        return false;
    }
}

Это далеко от того, к чему я привык в java, где реализация интерфейса Query выполняется прямо внутри метода odb.getObjects (). Если бы я где кодировал "java", я бы, вероятно, сделал что-то вроде следующего, но это не работает:

Objects<Prospect> src = odb.getObjects( {
        boolean match(p) { 
            if (p.url) {
            return p.url.endsWith(".biz");
        }
            return false; 
        }
    } as SimpleNativeQuery);

Или лучше, я бы хотел, чтобы это было так:

 Objects<Prospect> src = odb.getObjects( 
      { it.url.endsWith(".biz") } as SimpleNativeQuery
 );

Тем не менее, что это за отличный способ связать метод "match" с внешним контекстом сценария и подвести меня.

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


Мне следовало спросить, как мы проводим «анонимный» класс в Groovy. Вот идиома Java:

void defReadAFile() {
    File[] files = new File(".").listFiles(new FileFilter() {
        public boolean accept(File file) {
            return file.getPath().endsWith(".biz");
        }
    });
}

Может ли Groovy быть таким кратким без дополнительного объявления класса?


person Florin    schedule 17.04.2009    source источник


Ответы (3)


Я думаю, что это помогло бы вам получить ответы, если бы вы абстрагировались от проблемы, чтобы она не полагалась на интерфейс Neodatis DB - это привело меня в зацикливание, поскольку я никогда не использовал его. То, что я написал об этом ниже, основано на очень поверхностном анализе.

В этом отношении я тоже никогда не использовал Groovy, хотя мне нравится то, что я видел. Но поскольку никто еще не ответил, вы застряли со мной :-)

Я думаю, что проблема (или, по крайней мере, ее часть) может заключаться в том, что вы слишком многого ожидаете от класса SimpleNativeQuery от Neodatis. Не похоже, что он даже пытается фильтровать объекты перед добавлением их в возвращаемую коллекцию. Я думаю, вместо этого вы хотите использовать org.neodatis.odb.impl.core.query.criteria.CriteriaQuery. (Обратите внимание на «impl» в пути к пакету. Я немного нервничаю, так как я не знаю наверняка, предназначен ли этот класс для использования вызывающими абонентами. Но я не вижу любые другие классы в Neodatis, которые позволяют указывать критерии запроса.)

Но я думаю, что вместо прямого использования CriteriaQuery вы бы предпочли обернуть его внутри класса Groovy, чтобы можно было использовать его с замыканиями. Итак, я думаю, что Groovy-версия вашего кода с замыканиями может выглядеть примерно так:

// Create a class that wraps CriteriaQuery and allows you 
// to pass closures.  This is wordy too, but at least it's
// reusable.

import org.neodatis.odb.impl.core.query.criteria;

class GroovyCriteriaQuery extends CriteriaQuery {
    private final c;

    QProspect(theClosure) {
         // I prefer to check for null here, instead of in match()
         if (theClosure == null) {
             throw new InvalidArgumentException("theClosure can't be null!");
         }
         c = theClosure;
    }

    public boolean match(AbstractObjectInfo aoi){
        //!! I'm assuming here that 'aoi' can be used as the actual
        //!! object instance (or at least as proxy for it.)
        //!! (You may have to extract the actual object from aoi before calling c.)
        return c(aoi);
    }
}

// Now use the query class in some random code.

 Objects<Prospect> src = odb.getObjects( 
      new GroovyCriteriaQuery(
          { it.url.endsWith(".biz") } 
      )
 )

Надеюсь, это поможет!

person Dan Breslau    schedule 17.04.2009
comment
Вы правы, что вопрос слабый. То, что вы предоставили, действительно полезно, и я собираюсь его использовать, однако мне следовало спросить, как мы делаем анонимный класс в Groovy. Вот идиома java: void defReadAFile () {File [] files = new File (.). ListFiles (new FileFilter () {public boolean accept (File file) {return file.getPath () .ndsWith (.biz);} }); } Может ли Groovy быть таким же кратким без дополнительного объявления класса? - person Florin; 17.04.2009
comment
Я думаю, что комментарии нельзя форматировать так, как можно форматировать вопросы и ответы. - person Dan Breslau; 17.04.2009

Я считаю, что ваш реальный вопрос: «Могу ли я использовать замыкания вместо анонимных классов при вызове API Java, которые не используют замыкания». И ответ - однозначное «да». Этот:

 Objects<Prospect> src = odb.getObjects( 
      { it.url.endsWith(".biz") } as SimpleNativeQuery
 );

должно сработать. Вы пишете: «Однако, что делает groovy, чтобы связать метод« match »с внешним контекстом сценария и подвести меня». Как именно это выходит из строя? Мне кажется, что у вас возникла простая техническая проблема, связанная с поиском решения, которое было бы одновременно "отличным способом" и именно тем, с чем вы хотите работать.

person Michael Borgwardt    schedule 17.04.2009

Да, спасибо, все работает.

Я также узнал, почему SimpleNativeQuery не работает (по Дэну Бреслау).

Я пробовал следующее, и это прекрасно сработало. Итак, идиома работает так, как ожидалось.

new File("c:\\temp").listFiles({ it.path.endsWith(".html") } as FileFilter);

Следующий не работает из-за интерфейса neodatis. Интерфейс не применяет метод match ()! Он упоминает его только в документации, но его нет в файле класса:

public class SimpleNativeQuery extends AbstactQuery{

}

Objects<Prospect> src = odb.getObjects( 
  { it.url.endsWith(".biz") } as SimpleNativeQuery
);

В приведенном выше примере, поскольку SimpleNativeQuery не имеет метода match (), компилятор Groovy не может определить, к какому методу в SimpleNativeQuery следует присоединить замыкание; затем по умолчанию используется внешний Groovy-скрипт.

Это мой третий день с groovy, и мне это нравится.

Обе книги великолепны: - Groovy Recipes (Скотт Дэвис) - Programming Groovy (Venkat Subramaniam).

person Florin    schedule 17.04.2009