Sunny Arora
Sunny Arora

Reputation: 33

Facing issue while using reflection class concept in scala

I have one main class like this:

class Test {
  def exe(first:String, second:String, task:String):String = {
     task match {
       case "A" => {
          val obj = new A(first)
          obj.defineSecond(second)
       }
       case "B" => {
          val obj = new B(first)
          obj.defineSecond(second)
       }
       case "C" => {
          val obj = new C(first)
          obj.defineSecond(second)
       }
       ....so many cases
   }
 }
}

Instead of writing case in my Test class everytime a new class is added, I tried using the concept of reflection in scala. Below is what I trying:

val m = ru.runtimeMirror(getClass.getClassLoader)
val classTest = ru.typeOf[Test].typeSymbol.asClass
val cm = m.reflectClass(classTest)

But getting error as "class Test is inner class, use reflectClass on an InstaneMirror to obtain its classMirror".

Can anyone knows how can I can avoid adding cases to my main class everytime a new class is created, instead I can write my main class in a way it will work for every case.

Upvotes: 0

Views: 74

Answers (1)

Dmytro Mitin
Dmytro Mitin

Reputation: 51648

I guess you haven't provided all necessary information in your question. It's written that "class Test is inner class" in your error message but Test is not inner in your code snippet. If you want your runtime-reflection code to be fixed please provide code snippet that reflects actual use case.

Meanwhile you can try a macro (working at compile time)

import scala.language.experimental.macros
import scala.reflect.macros.blackbox

class Test {
  def exe(first: String, second: String, task: String): String = macro Test.exeImpl
}

object Test {
  def exeImpl(c: blackbox.Context)(first: c.Tree, second: c.Tree, task: c.Tree): c.Tree = {
    import c.universe._
    val cases = Seq("A", "B", "C").map(name =>
      cq"""${Literal(Constant(name))} => {
        val obj = new ${TypeName(name)}($first)
        obj.defineSecond($second)
      }"""
    )
    q"$task match { case ..$cases }"
  }
}

Usage:

class A(s: String) {
  def defineSecond(s1: String): String = ""
}
class B(s: String) {
  def defineSecond(s1: String): String = ""
}
class C(s: String) {
  def defineSecond(s1: String): String = ""
}

new Test().exe("first", "second", "task")

//scalac: "task" match {
//  case "A" => {
//    val obj = new A("first");
//    obj.defineSecond("second")
//  }
//  case "B" => {
//    val obj = new B("first");
//    obj.defineSecond("second")
//  }
//  case "C" => {
//    val obj = new C("first");
//    obj.defineSecond("second")
//  }
//}

Upvotes: 1

Related Questions