开发者

traversing between a trait (or class) methods

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜