我正在使用带有Groovy + Grails的MongoDB。虽然MongoDB Java API非常冗长,但Groovy能够像这样编写HashMaps来帮助实现这一点:
def map = [foo: "bar", one: "two"]
在MongoDB中,对象作为BasicDBObjects添加到数据库中,它扩展了HashMap,所以我可以在Groovy中写这样的东西:
things.save([ foo: "bar" ] as BasicDBObject)
虽然我不知道BasicDBOBject强制转换的来源(它是内置的,因为BasicDBObject已经从HashMap继承了吗?),如果我不需要每次都需要添加显式转换,那将是非常出色的坚持一个对象。
Groovy / Java是否有办法隐式地使超类子类转换,或者至少定义自定义隐式转换以避免在任何地方使用as运算符?
答案 0 :(得分: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
另请注意,它不需要方括号和parens。冒号放弃了地图的东西
对于as
方法,它是一个可以通过.asType(Class)
重载的运算符,我相信它有效,因为它试图实例化一个新的BasicDBObject
将地图作为参数传递在构造函数中。它可以在以下链接的第316行周围找到: