Is a Path Dependent Type a subtype?

人盡茶涼 提交于 2019-12-07 16:19:48

问题


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 
  }
}

Am I right that A.this.B is a path dependent type?! (That's my understanding so far) Does the example above mean that the type A.this.B is a subtype of A#B? (If yes, I guess the difference is that an instance of A.this.B has a reference to the instance of A compared to A#B which doesn't?) Does anyone know an enlightening explanation that resolves my confusion with these two types?


回答1:


The excellent book Programming in Scala has a pretty good explanation:

class Outer {
  class Inner
}

In Scala, the inner class is addressed using the expression Outer#Inner instead of Java's Outer.Inner. The . syntax is reserved for objects. For example, imagine you instantiate two objects of type Outer, like this:

val o1 = new Outer
val o2 = new Outer

Here o1.Inner and o2.Inner are two path-dependent types (and they are different types). Both of these types conform to (are subtypes of) the more general type Outer#Inner, which represents the Inner class with an arbitrary outer object of type Outer. By contrast, type o1.Inner refers to the Inner class with a specific outer object (the one referenced from o1). Likewise, type o2.Inner refers to the Inner class with a different, specific outer object (the one referenced from o2).

In Scala, as in Java, inner class instances hold a reference to an enclosing outer class instance. This allows an inner class, for example, to access members of its outer class. Thus you can't instantiate an inner class without in some way specifying an outer class instance. One way to do this is to instantiate the inner class inside the body of the outer class. In this case, the current outer class instance (referenced from this) will be used. Another way is to use a path-dependent type. For example, because the type, o1.Inner, names a specific outer object, you can instantiate it:

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

The resulting inner object will contain a reference to its outer object, the object referenced from o1. By contrast, because the type Outer#Inner does not name any specific instance of Outer, you can't create an instance of it:

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



回答2:


In short: Yes it is

If you want, you can consider A#B to have an abstract reference to the containing A (and therefore not directly constructable, as for any abstract type), this reference being made concrete in the path-dependent subclasses.




回答3:


Yes, it's a path dependent type. Yes, all instances of B are members of A#B. Note that you can't directly construct an instance of A#B, all instances of B must have a reference to the outer A instance



来源:https://stackoverflow.com/questions/5976791/is-a-path-dependent-type-a-subtype

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!