路径依赖类型与“基础类型”,哪些被检查?

路径依赖类型与“基础类型”,哪些被检查?

问题描述:

当使用反射来使用路径依赖类型时,即使我有匹配的“基础类型”,我也会遇到类型不匹配错误。什么是这些“非基础类型”,为什么他们检查而不是“基础类型”?路径依赖类型与“基础类型”,哪些被检查?

在下面的代码中,我想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的类型(这是),我预计这不会产生错误。由于某些原因,这些路径依赖类型在使用反射时与“基础类型”不同。为什么?

如果我不使用反射,它的工作原理:

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

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

这是我发现的唯一参考文献(on this forum)关于相同的错误,但它可能没有关系。

+0

谢谢您的询问!这真是奇怪,花了我一天的时间找到解决方法,最后看到你的帖子。 – 2013-04-14 18:20:13

这与反射没有任何关系。 b1b2的类型是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 

两个变量的类型为BB#ImplB,所以一切typechecks。

+0

我只是想到了这一点。表达“基础类型”有点令人误解,但它实际上意味着“父类型”。理想情况下,我想将newInst的返回类型转换为“className”类,但看起来在Scala中不可能。 – Adrian 2011-02-03 07:07:20

I just figured that out too. The expression "underlying type" is a bit misleading, while it actually means "parent type". Ideally I would like to cast the return type of newInst to the class of "className" but that looks like it is not possible in 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 
+0

我的意思是在返回之前,在newInst()中强制返回值。由于我没有可用的类型(我只有Class),所以我没有办法做到这一点。如果可能的话,类型检查器将能够在编译时根据运行时值(className)推断newInst()的类型 - 当然这是不可能的。我认为这也澄清了“基础类型”的含义。它是编译时已知的最具体的类型,而运行时类型只是作为object.type而已知我不确定“扩大单例”的含义。 b2不是单身人士。 – Adrian 2011-02-03 16:20:14