2

Groovy + Grailsを上に置いたMongoDBを使用しています。MongoDB Java API は非常に冗長ですが、Groovy は次のように HashMap を記述できるため、この点で役立ちます。

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

MongoDB では、オブジェクトは HashMap を拡張する BasicDBObjects としてデータベースに追加されるため、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 ) }

アイデアは単純です。オブジェクトに新しいメソッドを追加します。これは、Map を受け取り、それに応じて呼び出しをキャストにthingsリダイレクトする save() メソッドです。things.save(BasicDBObject)

必要に応じて、このメソッドを Thing のクラスに直接追加できます。

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 に答える