1

新しい Type Dynamic の使用を検討していますが、明らかなユース ケースが適切に実装されていないことがわかりました。オブジェクト指向データベース用の便利なラッパーを作成しようとしています。オブジェクトをシリアル化および逆シリアル化するため、キャストと使いやすさの問題に悩まされています(メソッドはオブジェクトを返します)。

最初の質問: 私のデータベースの get メソッドは、タイプ A のオブジェクトを逆シリアル化します。オブジェクトのみが表示されます。「基礎となる」オブジェクトが実際にそのメソッドを持っている場合、動的メカニズムは私のために試しますか、それともapplyDynamicで自分で処理する必要がありますか? REPLで試してみましたが、私にはそうではないようです。自分で確認する必要がある場合、最も簡単な方法は (scala の新しいリフレクションを使用するかどうかに関係なく)、そのオブジェクトにメソッド "methodname" があるかどうかを確認し、ある場合はそれを呼び出します。

このhttps://stackoverflow.com/a/11056410/703862に怖がっ て、メソッド呼び出し部分を非常に簡単に行うJavaのリフレクションにフォールバックします。

私はこれを思いつきます:

 scala> import java.lang.reflect.Method
 import java.lang.reflect.Method

 scala> class DynTest3 extends Dynamic {
 | def pee():String = "yuppie"
 |   def execSucced(method: Method, args: Any*):Boolean = return try{method.invoke(args); true} catch { case e: Exception => false }
 | def applyDynamic(methodName : String)(args: Any*){
 |     val succed = classOf[DynTest3].getDeclaredMethods.filter(m => m.getName() == methodName).exists(m => execSucced(m))
 | if (!succed)
 | throw new java.lang.NoSuchMethodException
 | }
 | }
 defined class DynTest3

しかし:

 scala> val y: Object = new DynTest3
 y: Object = DynTest3@74c74b55

 scala> y.asInstanceOf[Dynamic].pee()
 <console>:11: error: value applyDynamic is not a member of Dynamic
          y.asInstanceOf[Dynamic].pee()

基本的に、Dynamic にキャストしても、これは機能しません。ユーザーをキャストから救いたいので、ダイナミックにキャストすると、すでにすべてが役に立たなくなります。しかし、暗黙の変換 any2Dynamic を作成できるかもしれません...

ヒントはありますか?

4

1 に答える 1

6

Dynamicin Scala は、単純なコンパイル時の書き換えスキームです。詳細はSIP-17: Type Dynamicに記載されていますが、ここでは別の言葉で説明します。

dynamicメタオブジェクト、バインダー、コールサイト キャッシングのインフラストラクチャ全体を導入し、実行時にオーバーロードを処理するミニ C# コンパイラを実装するC# とは異なり、 Scala では可能な限り単純なものを使用することにしました。

コンパイル時の書き換えについて言及しましたが、今度は詳しく説明します。いくつかのルールがありますが、最も重要なものを見てみましょう。

foo.bar(arg1 ... argN) をコンパイルできず、foo が動的のサブタイプである静的型を持っている場合は、呼び出しを foo.applyDynamic("bar")(arg1 .. argN) に書き直します。書き換えられた式は、あたかもプログラマが手動で記述したかのように、通常どおり型チェックされます。

の場合y.asInstanceOf[Dynamic].pee()、呼び出しの受信者である y.asInstanceOf[Dynamic] は、間違いなく Dynamic をサブタイプする静的タイプであるため、書き換えがトリガーされます。書き換えた結果は ですy.asInstanceOf[Dynamic].applyDynamic("pee")()。ただし、Scala がこの式を型チェックしようとすると失敗します。Dynamic はメソッドを定義しない空のマーカー トレイトにすぎないためです。

この問題を解決するには、Dynamic のサブタイプで applyDynamic メンバーを持つものにキャストします (またはキャストせずに、API が Object ではなく何かを返すようにします)。これは自分で書くか、DynamicProxy (カスタム ロジックを組み込むためにサブクラス化されたもの) を使用することができます。これは 2.10.0-M5 に含まれることを願っています。

于 2012-07-03T08:11:51.423 に答える