Given the following object
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"
}
Is it possible to call all methods on this object, which the returned type is of MyOutput type?
Currenly I tried to use reflection for this, but had no luck with it.
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()
}
})
This is the error
scala.ScalaReflectionException: expected a member of class UniqueSingleType, you provided method
CodePudding user response:
val instanceMirror = m.reflect(functions)
should be instead of
val instanceMirror = m.reflect(typeOf[functions.type])
This was the mistake because it's functions
that is an instance, not typeOf[functions.type]
(which is UniqueSingleType
as written in the error).
Also there can be some improvements.
val classSymbol = m.classSymbol(functions.getClass)
val methods = classSymbol.info.members.filter(_.isMethod)
can be now replaced with
val methods = typeOf[functions.type].decls.toList.filter(_.isMethod)
since you know the object functions
at compile time (so you don't need .classSymbol
) and you're interested in the object methods rather than methods of its parents (so this is .decls
rather than .members
).
It's better to replace
method.info.resultType.toString.contains("MyOutput")
with
method.info.resultType =:= typeOf[String]
(aka method.info.resultType =:= typeOf[functions.MyOutput]
) in order not to rely on a work with raw strings.
In methodm()
you should provide arguments for the method:
methodm(...here...)