必要に応じて、スワップをトリガーする拡張メソッドとともに、基になるインスタンスをカバーの下で動的にスワップアウトできるように、プロキシパターンを実装しようとしています。これは以前に Java で実装したことがありますが、Scala ではうまくいきません。
これは私のシナリオです:
class Client { ...library code... }
trait DynamicClient extends Client {
def swap: Client
}
class Provider extends Provider[DynamicClient] {
def get():DynamicClient {
java.lang.reflect.Proxy.newProxyInstance(
classOf[DynamicClient].getClassLoader,
Array(classOf[DynamicClient]),
handler)
.asInstanceOf[DynamicClient]
}
}
class DynamicClientHandler extends java.lang.reflect.InvocationHandler {
var client:Client = createNewClient()
def swap(): {
client = createNewClient()
client
}
def createNewClient():Client: { ... }
def invoke(proxy: AnyRef, method: java.lang.reflect.Method, args: Array[AnyRef]): AnyRef = {
method.getDeclaringClass match {
case dyn if dyn == classOf[DynamicClient] => swap()
case _ => method.invoke(client, args: _*)
}
}
}
ここでの問題: Proxy オブジェクトの DynamicClient または Object からメソッドを呼び出すと、それらは問題なく動作します。
val dynamicClient = injector.instanceOf[DynamicClient]
val initial = dynamicClient.client
val client = dynamicClient.swap()
val dynamicClient.toString // "Client@1234" (Object impl of toString via client instance)
assert(client != initial) //passes just fine, the underlying client is re-initialized
Client クラスに属するメソッドへの呼び出しは、Invocation Handler に到達する前に失敗します。
//Both of the following scenarios fail independently of the other
//ERROR:
dynamicClient.asInstanceOf[Client]
//ERROR:
dynamicClient.doSomeClientMethod()
この例外トレースで:
java.lang.ClassCastException: com.sun.proxy.$Proxy22 cannot be cast to Client
このキャスト例外が発生するのはなぜですか? Scala と Java の方法でプロキシ呼び出し処理を処理するより良い方法はありますか?