是否有任何 Scala 功能允许您调用名称存储在字符串中的方法?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2060395/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 01:51:18  来源:igfitidea点击:

Is there any Scala feature that allows you to call a method whose name is stored in a string?

scaladynamiclanguage-features

提问by Geo

Assuming you have a string containing the name of a method, an object that supports that method and some arguments, is there some language feature that allows you to call that dynamically?

假设您有一个包含方法名称的字符串、一个支持该方法的对象和一些参数,是否有某种语言功能允许您动态调用它?

Kind of like Ruby's sendparameter.

有点像 Ruby 的send参数。

回答by Rex Kerr

You can do this with reflection in Java:

您可以使用 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)

And if you want it to be easy in Scala you can make a class that does this for you, plus an implicit for conversion:

如果你希望在 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")

Doing this sort of thing converts compile-time errors into runtime errors, however (i.e. it essentially circumvents the type system), so use with caution.

但是,执行此类操作会将编译时错误转换为运行时错误(即它本质上绕过了类型系统),因此请谨慎使用。

(Edit: and see the use of NameTransformer in the link above--adding that will help if you try to use operators.)

(编辑:并在上面的链接中查看 NameTransformer 的使用 - 如果您尝试使用运算符,添加这将有所帮助。)

回答by Jim Barrows

Yes. It's called reflection. Here's a link to one way, using some experimental stuffHowever you should remember that Scala is not a dynamic language, and may not be able to easily do some things that scripting languages can do. You're probably better doing a match on the string, and then calling the right method.

是的。这叫做反射。 这是一种方法的链接,使用一些实验性的东西但是您应该记住 Scala 不是一种动态语言,并且可能无法轻松完成脚本语言可以做的一些事情。您可能最好对字符串进行匹配,然后调用正确的方法。

回答by Vasily802

Yes you can!You would need .invoke()method of the method object. Simple example below:

是的你可以!您将需要.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 _ => ()}

see code here: https://scastie.scala-lang.org/vasily802/WRsRpgSoSayhHBeAvogieg/9

在这里查看代码:https: //scastie.scala-lang.org/vasily802/WRsRpgSoSayhHBeAvogieg/9

回答by Ravi

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