在特征(或类)方法之间遍历

时间:2011-02-23 08:08:46

标签: scala functional-programming

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)
}

我希望在t1,t2,t3之间进行遍历,而不需要像funcSet这样的Set

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

接受

1 个答案:

答案 0 :(得分:1)

执行此操作的方法仍然是使用反射,虽然这可以为您提供一些其他方法(如下面的toString):

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) }

然后使用结果遍历函数。当然,你可能比这更聪明,并根据参数的数量和类型过滤方法,并将包装器存储在底层地图中以访问它们。

编辑:

如果您有想要呼叫的方法的特定名称(例如t1),您可以这样做:

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

另一种实现此目的的方法是,如果在编译时已知方法名称,则在调用点使用结构类型:

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

请注意,您不能像以前一样使用字符串。这也是在引擎盖下使用反射。

此外,Scala中添加了一个新的Dynamic特征,其子类将允许使用在运行时获取的名称调用方法。这将在未来的某些版本中提供。