scala - 如何从 AnyRef 对象获取反射的运行时方法?

标签 scala reflection

我试图在一个实例中获取反射的运行时方法,但它没有显示在 decls 中结果:

val foo: AnyRef = new Object {
  def bar = 1
}
typeOf[foo.type].decls //Does not contain bar method

我尝试使用 Java 反射类并且它有效:
foo.getClass.getDeclaredMethods //It contains bar method

但是我更喜欢使用 MethodSymbols 和 Scala 类型而不是 Java 类和方法反射。如何获得反射的 MethodSymbol?

我想要一个方法来查找作为 AnyRef 传递给方法栏的对象并调用它。像下面这样:
def getBarMethodFromObj(obj: AnyRef): MethodSymbol = {
  //typeOf(obj).decl(TermName("bar")) this doesn't work
}

我不能使用 trait,因为 bar 可以有不同的参数和返回类型和数字。由于 Scala 不支持 varadic 泛型参数,我计划使用反射来查找方法和调用,但这在 Scala 中也无法完成。我目前正在使用 Java 解决方案:
val bar = foo.getClass.getDeclaredMethods.find(_.getName == "bar")
bar.invoke(foo, params: _*)

然而,Java 反射不保留泛型类型,因为它为 List 和 Map 等创建了问题。所以我想知道我是否可以在 Scala 中实现它,或者是否有任何即将到来的解决方案

最佳答案

我不知道你想做什么,但删除 AnyRef注释使您的代码工作:

val foo = new { def bar = 1 }
typeOf[foo.type].decls // Contains bar method

如果您需要类型注释(例如,在方法签名中),您可以使用编译器推断的相同结构类型:
val foo: { def bar: Int } = new { def bar = 1 }

如果你想从另一个方法中获取完整的方法列表而不知道确切的类型,除了通过泛型,你可能对 TypeTag 感兴趣。 :
import scala.reflect.runtime.universe.{ TypeTag, typeTag }
val foo = new { def bar = 1 }
def getMethods[T: TypeTag](t: T) = typeTag[T].tpe.decls
getMethods(foo) // Contains bar

如果您不能使用 TypeTag (可能是因为您无法更改 API),那么您最好使用 Java 反射 API。 Scala 反射 API 通常设计为使用类型信息,因此如果您只知道类型是 AnyRef,它可能对您不起作用。 .

回应您的编辑:

I cannot use trait because bar can have different argument and return types and numbers.



你当然可以:
trait Foo[A, B] {
  def bar(a: A): B
}

如果您需要多个参数,只需 bar取一个元组代替。如果你需要做一些元组不支持的列表操作,你可以考虑学习 HLists 和 shapeless .

However Java reflection does not retain generic types...



好吧,没有仅运行时的反射 API 会帮助你。根本无法找出 AnyRef 的通用参数是什么。在运行时有,因为该信息在 JVM 上不存在。使用类型标签,或使用 trait以上述方式。

关于scala - 如何从 AnyRef 对象获取反射的运行时方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51657139/

相关文章:

scala - Slick "==="仅编译用于理解

scala - 覆盖可堆叠特征模式中的抽象类型成员

斯卡拉玩 `Enumerators` : push or pull?

java - 如何在 ubuntu 上设置系统变量并在 scala 中检索它

oop - 是否有可能违反ABAP中的反射封装?

c# - 反射:Property-GetValue by Class-Type(因此没有实例化的对象)

java - 在这种情况下,如何参数化我的 Class 参数?

scala - 何时下载/构建 SBT 包?

c# - 动态创建类而不是使用开关 block 的最佳方法

c# - 检查文件是否为 .NET 程序集