我正在编写一个宏,并试图找到用于本地案例类的生成默认值的方法所在的位置。
例如,在顶级案例类中,例如:
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类的同伴对象在哪里?
答案 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类创建了配套对象。
我希望这能回答您的问题。