使用反射调用Scala对象上的所有方法

wnavrhmk  于 2023-02-04  发布在  Scala
关注(0)|答案(1)|浏览(143)

给定以下对象

object functions {

  type MyOutput = String

  def f1: MyOutput = "res1"

  def f2: MyOutput = "res2"

  def f3(foo: String): Boolean = foo.equals("bar")

  def f4(in:String): MyOutput = in+"res4"
}

是否可以调用此对象上的所有方法,其返回类型为MyOutput类型?
目前我尝试使用反射,但没有运气。

import scala.reflect.runtime.universe._

val m = runtimeMirror(getClass.getClassLoader)
val instanceMirror = m.reflect(typeOf[functions.type])
val classSymbol = m.classSymbol(functions.getClass)
val methods = classSymbol.info.members.filter(_.isMethod)
methods.foreach({
  method =>
    if (method.info.resultType.toString.contains("MyOutput")) {
      println(method.name.toString)
      val methodm = instanceMirror.reflectMethod(method.asMethod)
      methodm()
    }
})

这是错误scala.ScalaReflectionException: expected a member of class UniqueSingleType, you provided method

koaltpgm

koaltpgm1#

val instanceMirror = m.reflect(functions)

应改为

val instanceMirror = m.reflect(typeOf[functions.type])

这是一个错误,因为functions是一个示例,而不是typeOf[functions.type](错误中写的是UniqueSingleType)。
也可以有一些改进。

val classSymbol = m.classSymbol(functions.getClass)
val methods = classSymbol.info.members.filter(_.isMethod)

现在可以替换为

val methods = typeOf[functions.type].decls.toList.filter(_.isMethod)

因为您在编译时就知道对象functions(所以不需要.classSymbol),并且您对对象方法感兴趣,而不是其父对象的方法(所以这是.decls,而不是.members)。
最好换掉

method.info.resultType.toString.contains("MyOutput")

method.info.resultType =:= typeOf[String]

(aka method.info.resultType =:= typeOf[functions.MyOutput]),以便不依赖于具有原始字符串的作品。
methodm()中,您应该为方法提供参数:

methodm(...here...)

相关问题