【问题标题】:Facing issue while using reflection class concept in scala在scala中使用反射类概念时面临的问题
【发布时间】:2020-09-24 04:20:58
【问题描述】:

我有一个这样的主要课程:

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
   }
 }
}

我没有在每次添加新类时都在我的测试类中编写案例,而是尝试在 scala 中使用反射的概念。 以下是我尝试的:

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

但是由于“class Test是内部类,在InstaneMirror上使用reflectClass来获取它的classMirror”.

任何人都知道如何避免在每次创建新类时将案例添加到我的主类中,而是我可以编写我的主类以使其适用于每个案例。

【问题讨论】:

  • 老实说,我只想保持比赛。或者您可以使用Enumeratum 来定义您的所有任务,这样您就可以轻松地构建一个从名称到任务的地图。
  • 运行时反射很少是合适的解决方案

标签: scala reflection scala-reflect


【解决方案1】:

我猜你没有在你的问题中提供所有必要的信息。在您的错误消息中写道“类Test 是内部类”,但Test 在您的代码sn-p 中不是内部类。如果您希望修复运行时反射代码,请提供反映实际用例的代码 sn-p。

同时您可以尝试macro(在编译时工作)

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 }"
  }
}

用法:

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")
//  }
//}

【讨论】:

  • 谢谢!!我的实际类定义与仅测试相同。案例 'A','B' 只不过是规则类。要调用的规则类的名称在“任务:字符串”中,首先包含我必须应用规则的实际数据。 每次我实现新类时,我都必须添加 Test 类,所以需要这个东西是动态的,以便删除重复的代码,因为除了类名之外所有情况几乎相同。
  • @SunnyArora 再一次,在您的代码中,sn-p Test 不是内部的。它真的是内在的吗?然后请在其内部提供代码 sn-p。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-06-13
  • 1970-01-01
  • 2011-10-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多