我有一些作为对象的trait T
的方法签名列表,类似于以下内容,忽略了Arity:
case class Method[T,A,B](name: String, f: T => A => B)
因此,考虑到某些特征T
,它看起来像:
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))
)
我想创建一个类型为T
或与T
关联的类的实例,该实例使用Method
对象的字典来实现T
'的界面。
它可能看起来像以下内容(无法编译):
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
当然,返回的对象的类型为Object
,并且不能转换为类型/类T
。有什么办法可以解决此问题?
我有一个特征T
,我想为其创建远程调用接口。在客户端,我需要一个T
实例,该实例通过网络连接转发方法调用。我可以实现此RemoteT
。但是代码完全是样板。
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]
}
我认为我可以使用宏来综合方法覆盖并将它们转发到网络远程处理程序。但是我仍在尝试避免使用宏。
以下问题非常相关。我目前正在探索这种方法: Java Reflection: Create an implementing class
答案 0 :(得分:2)
我相信类似的事情也可以通过无形镜来实现。
Here,您会看到动力学将镜头的创建委托给隐式-返回的类型取自functional depenencies(此处为mkLens.Out
)
trait Lens[S, A] extends LPLens[S, A] { outer =>
...
def selectDynamic(k: String)
(implicit mkLens: MkSelectDynamicOptic[Lens[S, A], A, Symbol @@ k.type, Nothing]): mkLens.Out = mkLens(this)
...
}
镜头本身不是通过宏生成的,而是通过正常的派生生成的,但是you can use macro可以生成隐式的,它应该是可能的。
object Generic1 extends Generic10 {
...
implicit def mkGeneric10[T[_], U[_], FR[_[_], _[_]]]: Generic1[T, ({ type λ[t[_]] = FR[t, U] })#λ] =
macro Generic1Macros.mkGeneric1Impl[T, ({ type λ[t[_]] = FR[t, U] })#λ]
...
}
在HList中使用了宏+动态的组合。
object HList extends Dynamic {
...
/**
* Allows to specify an `HList` type with a syntax similar to `Record` and `Union`, as follows,
*
* {{{
* type ISB = HList.`Int, String, Boolean`.T
* }}}
*
* Literal types are allowed, so that the following is valid,
*
* {{{
* type ABC = HList.`'a, 'b, 'c`.T
* type TwoTrueStr = HList.`2, true, "str"`.T
* }}}
*/
def selectDynamic(tpeSelector: String): Any = macro LabelledMacros.hlistTypeImpl
...
}
总而言之,您应该能够实现自己的目标。这完全取决于您要实例化对象的精确程度-例如接受隐式ClassTag
并使用反射调用构造函数,或者构造HList
并使用Generic
将其转换为特定表示形式或其他某种形式。