Reflection 路径依赖类型vs.“;“基础类型”;,哪些是检查过的?

Reflection 路径依赖类型vs.“;“基础类型”;,哪些是检查过的?,reflection,scala,type-systems,path-dependent-type,abstract-type,Reflection,Scala,Type Systems,Path Dependent Type,Abstract Type,当将路径相关类型与反射一起使用时,即使有匹配的“底层类型”,我也会遇到类型不匹配错误。这些“非基础类型”是什么?为什么检查它们而不是“基础类型” 在下面的代码中,我希望compare方法只接受A的相同类型子类作为参数。错误在最后一行 abstract class A(val a:Int) { type Impl <: A def compare(other:Impl) { if(a==other.a) println("equal") else println("diff"

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

在下面的代码中,我希望
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
  }
}
由于b2的类型与b1的类型(即A)相同,因此我希望这不会产生错误。由于某些原因,在使用反射时,这些路径依赖类型与“底层类型”不同。为什么?

如果我不使用反射,它可以工作:

val b1 = new B(4)
val b2 = new B(5)
b1.compare(b2)  // no errors
(我确实需要在我的案例中使用反射)。是否可以使用反射将对象作为类“B”返回?这有帮助吗?使用抽象类型时是否有类型擦除


这是我找到的关于同一错误的唯一参考(),但可能没有关系。

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

在这个例子中

val b1 = new B(4)
val b2 = new B(5)
b1.compare(b2)  // no errors
这两个变量都有类型
B
,而
B#Impl
B
,因此所有类型都会检查


我也只是想出来了。这个 表达式“底层类型”有点复杂 误导,虽然它实际上意味着 “父类型”。理想情况下,我想 将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

我也发现了这一点。表达式“底层类型”有点误导,但实际上它的意思是“父类型”。理想情况下,我希望将newInst的返回类型强制转换为“className”类,但这在Scala中似乎是不可能的。我的意思是在newInst()内,在返回返回之前强制转换返回值。因为我没有可用的类型(我只有类),所以我看不到一种方法。如果可能的话,类型检查器将能够在编译时根据运行时值(类名)推断newInst()的类型-这当然是不可能的。我想这也澄清了“底层类型”的含义“。它是编译时已知的最具体的类型,而运行时类型仅称为object.type。我不确定您所说的“扩展单例”是什么意思。”。b2不是一个单体。b2绝对是一个单体。你认为“b2.type”是什么意思?这是b2的类型。不是b1、b3或世界上任何其他类型。它的底层类型,它是一个实例,是A。b2是B的实例,转换为A。它不是一个单例,在我的书(PinS)中,它是一个用“object”关键字定义的对象。我在这里遗漏了什么?您遗漏了很多类型系统,它是围绕单例类型构建的。“object”关键字定义了一个具有单个实例的类。对象的类型是单例类型。但是其他很多东西都有单例类型。无论何时使用路径引用类型(如“b2.Impl”),前缀都必须是稳定的。我建议您参考说明书,其中对所有这些都进行了详细的解释。艰苦的学习仍然被称为学习,对吗?谢谢,@即席谢谢你的邀请!这真的很奇怪,我花了一天的时间找到了解决办法,终于看到了你的帖子。
def main(args: Array[String]) {
  val b1 = newInst(4, "B")
  val b2 = newInst(5, "B")
  b1.compare(b2.asInstanceOf[b1.Impl])
}
% scala Test
diff