路径依赖类型是子类型吗?

时间:2011-05-12 10:41:59

标签: scala path-dependent-type

trait A {
  trait B {
    def foo: A.this.B = new B{}
    def bar: A#B      = foo 
    def baz: A.this.B = bar // type mismatch; found : A#B required: A.this.B 
  }
}

我是对的,A.this.B是路径依赖类型吗?! (这是我迄今为止的理解) 上面的示例是否意味着类型A.this.B A#B的子类型? (如果是,我猜不同之处在于A.this.B的实例引用了AA#B相比的实例,而不是{{1}}? 有没有人知道一个启发性的解释,解决了我对这两种类型的困惑?

3 个答案:

答案 0 :(得分:14)

出色的书籍Scala编程非常好explanation

class Outer {
  class Inner
}

在Scala中,使用表达式Outer#Inner而不是Java的Outer.Inner来解决内部类。 .语法是为对象保留的。例如,假设您实例化了两个类型为Outer的对象,如下所示:

val o1 = new Outer
val o2 = new Outer

此处o1.Innero2.Inner是两种与路径相关的类型(它们是不同的类型)。这两种类型都符合(是子类型)更通用的类型Outer#Inner,它表示具有Outer类型的任意外部对象的Inner类。相反,类型o1.Inner是指具有特定外部对象(从o1引用的那个)的Inner类。同样,类型o2.Inner引用具有不同的特定外部对象的Inner类(从o2引用的对象)。

在Scala中,与Java一样,内部类实例包含对封闭外部类实例的引用。例如,这允许内部类访问其外部类的成员。因此,如果不以某种方式指定外部类实例,则无法实例化内部类。一种方法是在外部类的实体内实例化内部类。在这种情况下,将使用当前外部类实例(从中引用)。另一种方法是使用路径依赖类型。例如,因为类型o1.Inner命名特定的外部对象,所以可以实例化它:

scala> new o1.Inner
res1: o1.Inner = Outer$Inner@13727f

生成的内部对象将包含对其外部对象的引用,该对象是从o1引用的对象。相比之下,因为类型Outer#Inner没有命名Outer的任何特定实例,所以您无法创建它的实例:

scala> new Outer#Inner
<console>:6: error: Outer is not a legal prefix for
  a constructor
       new Outer#Inner
                 ^

答案 1 :(得分:5)

简而言之:是的,

如果需要,可以考虑A#B对包含A的抽象引用(因此不能直接构造,如同任何抽象类型),此引用在路径中具体化 - 依赖的子类。

答案 2 :(得分:2)

是的,它是路径依赖类型。是的,B的所有实例都是A#B的成员。请注意,您不能直接构造A#B的实例,B的所有实例必须具有对外部A实例的引用