问题描述:

trait t{

val y = "z"

def t1(x:String):String=x+"a"+y

def t2(x:String):String= x+"b"+y

def t3(x:String):String= x+"c"+y

}

class c extends t {

val funcSet = Set(t1 _,t2 _,t3 _)

def multiBitamin(input:String) = for(f <- funcSet) yield f(input)

}

I want traverse between t1,t2,t3 without having a Set like funcSet

val funcSet = Set("t1","t2","t3")

accepted

网友答案:

The way to do this is still to use reflection, although this can give you some additional methods (like toString below):

scala> trait t{
     |   val y = "z"
     |   def t1(x:String):String=x+"a"+y
     |   def t2(x:String):String= x+"b"+y
     |   def t3(x:String):String= x+"c"+y
     | }
defined trait t

scala> val inst = new t{}

scala> inst.getClass.getMethods.filter(_.getName.startsWith("t")) map { m => (s: String) => m.invoke(inst, s) }

and then use the result to traverse the functions. Of course, you could be smarter than this, and filter the methods according to the number of parameters and their types, and store the wrappers in an underlying map to access them.

EDIT:

If you have a specific name of a method you wish to call (say t1), you can do:

scala> val f = (s: String) => inst.getClass.getMethods.find(_.getName == "t1").get.invoke(inst, s)                  
f: (String) => java.lang.Object = <function1>

Another way to accomplish this is to use structural types at the callsite if the method name is known at compile time:

scala> (inst: AnyRef).asInstanceOf[{def t1(s: String): String}].t1("Hello ")
res9: String = Hello az 

Note that you cannot use a string here, like before. This also uses reflection under the hood.

Also, a new Dynamic trait is being added to Scala, subclasses of which will allow calling a method using its name obtained at runtime. This will be available in some of the future releases.

相关阅读:
Top