我试图在一个实例中获取反射的运行时方法,但它没有显示在 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/