I have a list of method signatures of some trait T
given as objects, similar to the following, ignoring arity:
case class Method[T,A,B](name: String, f: T => A => B)
So given some trait T
, this could look like:
trait T{
def foo(i: Int): String
def bar(s: String): Unit
}
def methodsOfT: Seq[Method[T,_,_]] = Seq(
Method("foo", t => i => t.foo(i)),
Method("bar", t => s => t.bar(s))
)
I want to create an instance of type T
, or of the class associated with T
, whatever, that uses a dictionary of Method
objects to implement T
's interface.
It could look like the following (this won't compile):
def reify[T](impl: T, methods: Method[T,_,_]): T = (new Object with Dynamic {
def applyDynamic(method: String)(args: Any*): Any = {
//do something here
}
}).asInstanceOf[T] //<- will fail at runtime
Of course the returned object is of type Object
, and cannot be cast to type/class T
. Is there any way to work around this problem?
Why I want to do this
I have a trait T
for which I want to create a remote invocation interface. On the client side, I need an instance of T
that forwards method invocations over a network connection. I could implement this RemoteT
. But the code is completely boilerplate.
new T {
def foo(i: Int): String =
methodsOfT.find(_.name == "foo").get.f(i).asInstanceOf[String]
def bar(s: String): Unit =
methodsOfT.find(_.name == "bar").get.f(s).asInstanceOf[Unit]
}
I think I could use macros to synthesize the method overrides and forward them to the network remote handler. But I'm still trying to avoid macros.
P.S.
The following question is very related. I'm currently exploring this approach: Java Reflection: Create an implementing class