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

吃可爱长大的小学妹 提交于 2019-11-27 19:08:10

You can do this with reflection in 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:

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

Yes. It's called reflection. Here's a link to one way, using some experimental stuff However 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.

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

 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

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
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!