2

我在顶部使用带有 Groovy + Grails 的 MongoDB。虽然 MongoDB Java API 非常冗长,但 Groovy 在这方面提供了帮助,因为它能够像这样编写 HashMap:

def map = [foo: "bar", one: "two"]

在 MongoDB 中,对象作为 BasicDBObjects 添加到数据库中,它扩展了 HashMap,因此我可以在 Groovy 中编写如下内容:

things.save([ foo: "bar" ] as BasicDBObject)

虽然我不知道 BasicDBOBject 演员表来自哪里(它是内置的,因为 BasicDBObject 已经从 HashMap 继承了吗?),如果我不必每次都添加显式演员表我想坚持一个目的。

Groovy/Java 是否有办法使超类-子类强制转换为隐式,或者至少定义自定义隐式强制转换以避免在任何地方使用 as 运算符?

4

1 回答 1

2

好吧,如果您在使用 Groovy,为什么不进行一些元编程呢?:-)

things.metaClass.save = { Map map -> delegate.save( map as BasicDBObject ) }

这个想法很简单:我们在things对象上添加一个新方法,它是一个 save() 方法,它接收一个 Map 并将调用重定向到相应的things.save(BasicDBObject)转换。

如果需要,可以直接将此方法添加到事物的类中:

ThingsClass.metaClass.save = { Map map -> delegate.save( map as BasicDBObject ) }

我写了下面的脚本试图模拟你所描述的,我希望我做对了:

class BasicDBObject extends HashMap { }

class Mongo {
    def save(BasicDBObject obj) {
        println "saving $obj"
    }
}

def mongo = new Mongo()

// here it will fail
try {
    mongo.save uno:1, dos:2
    assert false
} catch (e) { }


mongo.metaClass.save = { Map map -> delegate.save( map as BasicDBObject ) }

// and here it succeeds ;-)
mongo.save uno:1, dos:2 

另请注意,它不需要方括号和括号。冒号放弃了地图的东西

对于该as方法,它是一个可以通过 重载的运算符.asType(Class),我相信它可以工作,因为它尝试实例化一个新BasicDBObject的,将映射作为构造函数中的参数传递。可以在以下链接的第 316 行附近找到它:

https://github.com/groovy/groovy-core/blob/master/src/main/org/codehaus/groovy/runtime/typehandling/DefaultTypeTransformation.java

于 2012-08-11T20:00:02.840 回答