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
的实例引用了A
与A#B
相比的实例,而不是{{1}}?
有没有人知道一个启发性的解释,解决了我对这两种类型的困惑?
答案 0 :(得分:14)
出色的书籍Scala编程非常好explanation:
class Outer {
class Inner
}
在Scala中,使用表达式Outer#Inner
而不是Java的Outer.Inner
来解决内部类。 .
语法是为对象保留的。例如,假设您实例化了两个类型为Outer
的对象,如下所示:
val o1 = new Outer
val o2 = new Outer
此处o1.Inner
和o2.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实例的引用