我正在尝试在实例中获取反映的运行时方法,但未在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 Type,而不是Java类和方法反射。如何获得反映的MethodSymbol?
我想要一个方法来查找作为方法栏的AnyRef传递的对象并对其进行调用。如下所示:
def getBarMethodFromObj(obj: AnyRef): MethodSymbol = {
//typeOf(obj).decl(TermName("bar")) this doesn't work
}
我不能使用trait,因为bar可以具有不同的参数以及返回类型和数字。由于Scala不支持可变的泛型参数,因此我计划使用反射来查找方法和调用,但这在Scala中也无法做到。我目前正在使用Java解决方案:
val bar = foo.getClass.getDeclaredMethods.find(_.getName == "bar")
bar.invoke(foo, params: _*)
但是Java反射并不会保留泛型类型,因为它会为List和Map等带来问题。所以我想知道我是否可以在Scala中实现它,或者有什么解决方案
答案 0 :(得分:6)
我不知道您要做什么,但是删除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 Reflection API。 Scala反射API通常设计为使用类型信息,因此,如果您仅知道类型为AnyRef
,它可能对您不起作用。
根据您的修改:
我不能使用特征,因为bar可以具有不同的参数以及返回类型和数字。
确定可以:
trait Foo[A, B] {
def bar(a: A): B
}
如果需要多个参数,只需让bar
取一个元组即可。如果您需要执行一些元组不支持的列表操作,则可以考虑了解HList和shapeless。
但是Java反射不能保留通用类型...
好吧,仅运行时反射API不会为您提供帮助。根本无法找出运行时AnyRef
具有哪些通用参数,因为JVM上不存在该信息。使用TypeTag,或以上述方式使用trait
。