默认参数值方法位置

时间:2018-08-17 01:08:01

标签: scala scala-macros

我正在编写一个宏,并试图找到用于本地案例类的生成默认值的方法所在的位置。

例如,在顶级案例类中,例如:

package foo

case class Goo(a: String = "wibble")

我可以轻松地找到返回“摆动”的方法,该方法如<init>$default$N的伴随对象上定义的Goo一样。像这样:

val defswithsymbols = universe.asInstanceOf[Definitions with SymbolTable with StdNames]
val defaultGetter = defswithsymbols.nme.defaultGetterName(defswithsymbols.nme.CONSTRUCTOR, index + 1)
val method = tpe.companion.member(TermName(defaultGetter.toString))

然后我可以调用tpe.companion上的方法来给我默认值。

但是,如果我在方法内部定义了一个case类,则该类没有伴侣对象(可以找到),因此无法找到默认的参数生成方法。但必须在正确的位置定义它:)

编辑:我认为这个问题可能可以归结为-在方法内声明的case类的同伴对象在哪里?

1 个答案:

答案 0 :(得分:0)

编译案例类时,编译器会为主类及其配套对象创建类文件。对于在方法内部定义的案例类,其操作相同。唯一的区别是,使用无法访问的文件名创建了类文件。它有点类似于匿名类文件名。

例如:

class TestClass {
  new Runnable(){
     def run() = {
        //some Code
     }
  }
}

编译上面的代码后,编译器可能会生成名称为 TestClass $ anon $ 1 的类文件。如果知道此名称,则可以使用反射创建此匿名内部类的实例。

请参考下面的示例代码以及在方法内部定义的case类。

class TestClass {
  def someMethod = {
    case class ClassInsideMethod()
  }
}

object Main extends App{
  val enclosingClass = classOf[TestClass]
  val enclosingInstance = Class.forName(enclosingClass.getName).newInstance().asInstanceOf[TestClass]
  private val classInsideMethodConstructor = Class.forName(enclosingClass.getName + "$ClassInsideMethod$2").getDeclaredConstructor(enclosingClass)
  classInsideMethodConstructor.newInstance(enclosingInstance)
}

我发现编译代码后,编译器确实为案例类创建了名为 TestClass $ ClassInsideMethod $ 2 TestClass $ ClassInsideMethod $ 3 $ 的类文件。类文件后附有数字。根据您的编译器,此命名将有所不同。就我而言,通过反射,我能够创建方法内部定义的case类的实例。

TLDR;编译器确实为case类创建了配套对象。

我希望这能回答您的问题。