Есть ли какая-либо функция Scala, которая позволяет вам вызывать метод, имя которого хранится в строке? - PullRequest
17 голосов
/ 14 января 2010

Предполагая, что у вас есть строка, содержащая имя метода, объект, который поддерживает этот метод, и некоторые аргументы, есть ли какая-либо языковая функция, которая позволяет вызывать это динамически?

Вроде как параметр send Руби.

Ответы [ 4 ]

31 голосов
/ 14 января 2010

Вы можете сделать это с помощью отражения в Java:

class A {
  def cat(s1: String, s2: String) = s1 + " " + s2
}
val a = new A
val hi = "Hello"
val all = "World"
val method = a.getClass.getMethod("cat",hi.getClass,all.getClass)
method.invoke(a,hi,all)

И если вы хотите, чтобы в Scala это было легко, вы можете создать класс, который сделает это за вас, плюс неявный для преобразования:

case class Caller[T>:Null<:AnyRef](klass:T) {
  def call(methodName:String,args:AnyRef*):AnyRef = {
    def argtypes = args.map(_.getClass)
    def method = klass.getClass.getMethod(methodName, argtypes: _*)
    method.invoke(klass,args: _*)
  }
}
implicit def anyref2callable[T>:Null<:AnyRef](klass:T):Caller[T] = new Caller(klass)
a call ("cat","Hi","there")

Подобные действия преобразуют ошибки времени компиляции в ошибки времени выполнения (т. Е. По существу обходят систему типов), поэтому используйте их с осторожностью.

(Изменить: и посмотреть использование NameTransformer по ссылке выше - добавление, которое поможет, если вы попытаетесь использовать операторы.)

6 голосов
/ 14 января 2010

Да. Это называется отражением. Вот ссылка на один способ, используя некоторые экспериментальные вещи Однако вы должны помнить, что Scala не является динамическим языком и может не иметь возможности легко делать некоторые вещи, которые могут делать языки сценариев. Возможно, вам лучше выполнить сопоставление строки и затем вызвать правильный метод.

3 голосов
/ 17 марта 2017

Да, вы можете! Вам понадобится .invoke() метод объекта метода. Простой пример ниже:

 import scala.util.Try

 case class MyCaseClass(i: String) {
 def sayHi = {
     println(i)
   }
 }
 val hiObj = MyCaseClass("hi")
 val mtdName = "sayHi"
 // Method itself as an object
 val mtd = hiObj.getClass.getMethod(mtdName)
 Try {mtd.invoke(hiObj)}.recover { case _ => ()}

см. Код здесь: https://scastie.scala -lang.org / vasily802 / WRsRpgSoSayhHBeAvogieg / 9

1 голос
/ 04 октября 2015
scala> val commandExecutor = Map("cleanup" -> {()=> println("cleanup successfully")} )
commandExecutor: scala.collection.immutable.Map[String,() => Unit] = Map(cleanup -> <function0>)

scala> val command="cleanup"
command: String = cleanup

scala> commandExecutor(command).apply
cleanup successfully
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...