3

当使用带有反射的路径相关类型时,即使我有匹配的“基础类型”,我也会收到类型不匹配错误。这些“非基础类型”是什么?为什么要检查它们而不是“基础类型”?

在下面的代码中,我希望该compare方法只接受 A 的相同类型的子类作为参数。错误在最后一行。

abstract class A(val a:Int) {
  type Impl <: A
  def compare(other:Impl) {
    if(a==other.a) println("equal") else println("diff")
  }
}
class B(a:Int) extends A(a) {type Impl = B}

object Test {
  def newInst(a: Int, className: String) = {
    val constr = Class.forName(className).getConstructors()(0)
    constr.newInstance(a.asInstanceOf[AnyRef]).asInstanceOf[A]
  }

  def main(args: Array[String]) {
    val b1 = newInst(4, "B")
    val b2 = newInst(5, "B")
    b1.compare(b2)   // type mismatch error here
  }
}

在最后一行我得到这个错误:

error: type mismatch;
found   : b2.type (with underlying type A)
required: b1.Impl

由于 b2 的类型与 b1 的类型(即 A)相同,因此我希望这不会产生错误。由于某种原因,这些依赖于路径的类型在使用反射时不同于“基础类型”。为什么?

如果我不使用反射,它会起作用:

val b1 = new B(4)
val b2 = new B(5)
b1.compare(b2)  // no errors

(在我的情况下,我确实需要使用反射)。可以newInst()使用反射将对象作为“B”类返回吗?这会有帮助吗?使用抽象类型时是否有类型擦除?

这是我发现(在这个论坛上)关于相同错误的唯一参考,但它可能不相关。

4

2 回答 2

5

这与反射无关。b1and的类型b2A(因为这是 的返回类型newInst)。b1.compare(b2)对于编译调用,b2必须具有 type b1.Impl。编译器只知道它是 的某个子类型A,但不知道是哪一个。由于您无法传递需要A某些子类型的A位置,因此您会收到错误消息。

在示例中

val b1 = new B(4)
val b2 = new B(5)
b1.compare(b2)  // no errors

两个变量都有 typeBB#Implis B,所以一切都进行了类型检查。

于 2011-02-03T06:44:33.823 回答
5

我也刚想通了。“底层类型”的表达有点误导,而它实际上意味着“父类型”。理想情况下,我想将 newInst 的返回类型转换为“className”类,但这看起来在 Scala 中是不可能的。"

这并不意味着“父类型”。这种类型确实是父母。底层类型是指单例类型的扩展。数字 5 的类型是单例;它的基础类型是 Int。大多数人不会将 Int 称为“父类型”。(尽管,再次,它是。)

至于问题,你可以投它。没有什么能挡住你的路:scala 不会,java 也不会。

def main(args: Array[String]) {
  val b1 = newInst(4, "B")
  val b2 = newInst(5, "B")
  b1.compare(b2.asInstanceOf[b1.Impl])
}
% scala Test
diff
于 2011-02-03T08:28:59.463 回答