Scala反射 - 没有调用的构造函数

时间:2016-09-05 11:19:16

标签: scala reflection

我创建了一个扩展B类的A类,它接受两个参数。

当我使用反射创建A的类对象并传递两个参数时,一个对象创建没有任何异常,但是这两个“构造函数”参数不包含我传递的值。 这是预期的行为还是我做错了什么?

示例代码:

class B (p1: Int = 0, p2: String = "") {
...
}

class A extends B {
...
}


val mirror = universe.runtimeMirror(getClass.getClassLoader)
val classSymbol = mirror.classSymbol(Class.forName("package.A"))
val constructor = mirror.reflectClass(classSymbol).reflectConstructor(
                 classSymbol.toType.decl(universe.termNames.CONSTRUCTOR).asMethod)
val object: B = constructor(1, "C").asInstanceOf[B]

“object”包含A的实例,但p1 = 0且p2 =“”。我希望它包含p1 = 1和p2 =“C”。

如果我将(p1: Int = 0, p2: String = "")移到A,它会按预期工作。

这是正常的行为,我的期望是错的,还是我的代码中有错误?

2 个答案:

答案 0 :(得分:1)

我不知道潜在的原因,但它可能与反射在运行时如何工作的一些怪癖有关。

在任何情况下,这种代码都能为您提供所需的代码(不重复超类中指定的默认值)。请注意,您应该在子类中使用的超类中显式指定参数:

class B (p1: Int = 0, p2: String = "") {
  override def toString: String = s"p1 = $p1, p2 = $p2"
}

class A (p1: Int, p2: String) extends B (p1, p2) { }

...

val obj: B = constructor(1, "C").asInstanceOf[B]
println(obj)

输出:

p1 = 1, p2 = C

答案 1 :(得分:1)

让我们首先完全从图片中反射出来,并尝试不使用反射来做你正在做的事情:

class B(p1: Int = 0, p2: String = "")

class A extends B

//val b = (new A(1, "C")).asInstanceOf[B]

// even simpler:
val b = new A(1, "C")
// error: too many arguments for constructor A: ()A
//        new A(1, "C")
//        ^

正如您所看到的,它甚至无法编译。为什么?好吧,你定义A的构造函数不带参数!不知何故,在反思过程中,这些信息会丢失,你最后会通过合法的调用将参数传递给一个没有任何东西的构造函数而忽略它们。