【发布时间】:2018-11-22 12:29:39
【问题描述】:
我想通过反射调用任意东西的任意公共方法。 IE。比方说,我想编写方法extractMethod 来使用:
class User { def setAvatar(avatar: Avatar): Unit = …; … }
val m = extractMethod(someUser, "setAvatar")
m(someAvatar)
从 Scala 文档的 Reflection. Overview 文档中,我看到了以下直接方法:
import scala.reflect.ClassTag
import scala.reflect.runtime.universe._
def extractMethod[Stuff: ClassTag: TypeTag](
stuff: Stuff,
methodName: String): MethodMirror =
{
val stuffTypeTag = typeTag[Stuff]
val mirror = stuffTypeTag.mirror
val stuffType = stuffTypeTag.tpe
val methodSymbol = stuffType
.member(TermName(methodName)).asMethod
mirror.reflect(stuff)
.reflectMethod(methodSymbol)
}
但是,我对这个解决方案感到困扰的是,我需要传递隐式的 ClassTag[Stuff] 和 TypeTag[Stuff] 参数(第一个用于调用 reflect,第二个用于获取 stuffType)。这可能非常麻烦,特别是如果从泛型调用的泛型调用extractMethod 等等。对于某些严重缺乏运行时类型信息的语言,我认为这是必要的,但 Scala 基于 JRE,它允许执行以下操作:
def extractMethod[Stuff](
stuff: Stuff,
methodName: String,
parameterTypes: Array[Class[_]]): (Object*) => Object =
{
val unboundMethod = stuff.getClass()
.getMethod(methodName, parameterTypes: _*)
arguments => unboundMethod(stuff, arguments: _*)
}
我了解 Scala 反射允许获取比基本 Java 反射更多的信息。不过,在这里我只需要调用一个方法。有没有办法以某种方式减少基于 Scala 反射的extractMethod 版本的要求(例如这些ClassTag,TypeTag)(不回退到纯 Java 反射),假设性能对我来说并不重要?
【问题讨论】:
标签: scala reflection scala-reflect