Способ сделать это - все еще использовать отражение, хотя это может дать вам несколько дополнительных методов (как 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) }
, а затем используйте результат для обхода функций. Конечно, вы можете быть умнее этого и фильтровать методы по количеству параметров и их типам, а также сохранять обертки в базовой карте для доступа к ним.
EDIT:
Если у вас есть конкретное имя метода, который вы хотите вызвать (скажем, 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
, подклассы которой позволяют вызывать метод, используя его имя, полученное во время выполнения. Это будет доступно в некоторых будущих выпусках.