最好的groovy闭包成语取代java内部类?

时间:2009-04-17 01:42:42

标签: groovy closures

作为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
 );

然而,将“匹配”方法与外部脚本上下文相关联并使我失败的是groovy。

我发现groovy ......不管怎么说,所以我会坚持学习更多关于它的内容。感谢。


我应该问的是我们如何在groovy中进行“匿名”课程。这是java习语:

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

groovy可以简洁,没有额外的类声明吗?

3 个答案:

答案 0 :(得分:1)

我认为如果你提取问题以便它不依赖于Neodatis数据库接口,这会帮助你得到答案 - 这让我陷入了循环,因为我从未使用它。我在下面写的关于它的内容是基于粗略的分析。

就此而言,我从未使用过Groovy,尽管我喜欢我所见过的。但看到没有其他人回答,你仍然坚持我: - )

我认为问题(或至少部分问题)可能是你期望Neodatis的SimpleNativeQuery类过多。在将对象添加到返回的集合之前,它甚至不会尝试过滤对象。我想你想要使用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") } 
      )
 )

我希望这有帮助!

答案 1 :(得分:1)

我相信你真正的问题是“在调用不使用闭包的Java API时,我可以使用闭包而不是匿名类”。答案肯定是“是”。这样:

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

应该有效。你写了“但是,将”匹配“方法与外部脚本上下文相关联并使我失败的是什么groovy”。它到底是怎么失败的?在我看来,你有一个简单的技术问题,以获得既“时髦的方式”和你想要工作的解决方案。

答案 2 :(得分:0)

是的,谢谢你们,它确实有效。

我还发现了为什么SimpleNativeQuery不起作用(根据Dan Breslau)。

我尝试了以下内容并且效果非常好。所以成语确实按预期工作。

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(斯科特戴维斯) - 编程Groovy(Venkat Subramaniam)