Groovy / Java可以隐式地转换为子类(或具有自定义隐式转换)吗?

时间:2012-08-10 13:45:41

标签: java types groovy casting

我正在使用带有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运算符?

1 个答案:

答案 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行周围找到:

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