Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Compiling this with <code>-explaintypes</code> yields:</p> <pre><code>&lt;console&gt;:11: error: illegal inheritance; self-type GraphKind.this.G does not conform to Collection[T]'s selftype Collection[T] abstract class Graph[T] extends Collection[T]{ ^ GraphKind.this.G &lt;: Collection[T]? Iterable[T] &lt;: Iterable[T]? T &lt;: T? T &lt;: Nothing? &lt;notype&gt; &lt;: Nothing? false Any &lt;: Nothing? &lt;notype&gt; &lt;: Nothing? false false false Any &lt;: T? Any &lt;: Nothing? &lt;notype&gt; &lt;: Nothing? false false false false false GraphKind.this.Graph[T] &lt;: Iterable[T]? Iterable[T] &lt;: Iterable[T]? T &lt;: T? T &lt;: Nothing? &lt;notype&gt; &lt;: Nothing? false Any &lt;: Nothing? &lt;notype&gt; &lt;: Nothing? false false false Any &lt;: T? Any &lt;: Nothing? &lt;notype&gt; &lt;: Nothing? false false false false false false false </code></pre> <p>Now, I was about to write <em>I don't understand how <code>T &lt;: T</code> can be false -- it is almost like <code>T</code> was defined twice</em>, which, of course, is the whole problem. Here:</p> <pre><code>abstract class GraphKind[T] { type V &lt;: Vertex[T] type G &lt;: Graph[T] def newGraph(): G abstract class Graph[T] extends Collection[T]{ </code></pre> <p>Ok, class <code>GraphKind</code> is parameterized with <code>T</code> and type <code>G</code> must be a <code>Graph[T]</code>. Now, class <code>Graph</code> is also parameterized, and its parameter is also called <code>T</code>. To prevent confusing, let's rewrite it:</p> <pre><code> abstract class Graph[T2] extends Collection[T2]{ self: G =&gt; def vertices(): List[V] def add(t: T2): Unit def size(): Int def elements(): Iterator[T2] } </code></pre> <p>Note that this is EXACTLY EQUAL to what you wrote. I'm just using a different name for the type parameter, so that it doesn't get confused with the <code>T</code> that is parameterizing <code>GraphKind</code>.</p> <p>So, here is the logic:</p> <pre><code>G &lt;: Graph[T] Graph[T2] &lt;: Collection[T2] Graph[T2] &lt;: G // self type </code></pre> <p>which implies that</p> <pre><code>Graph[T2] &lt;: Graph[T] </code></pre> <p>And, because <code>Graph</code> extends <code>Collection</code>:</p> <pre><code>Collection[T2] &lt;: Collection[T] </code></pre> <p>But there is no guarantee that this is true. I do not understand why the problem does not show up when the inheritance is not present. Fix:</p> <pre><code>abstract class GraphKind[T] { type V &lt;: Vertex type G &lt;: Graph def newGraph(): G abstract class Graph extends Collection[T]{ self: G =&gt; def vertices(): List[V] def add(t: T): Unit def size(): Int def elements(): Iterator[T] } trait Vertex { self: V =&gt; def graph(): G def value(): T } } class SimpleGraphKind[T] extends GraphKind[T] { type G = GraphImpl type V = VertexImpl def newGraph() = new GraphImpl class GraphImpl extends Graph { private var vertices_ = List[V]() def vertices = vertices_ def add( t: T ) { vertices_ ::= new VertexImpl(t,this) } override def size() = vertices_.size override def elements() = vertices.map( _.value ).elements } class VertexImpl(val value: T, val graph: GraphImpl) extends Vertex { override lazy val toString = "Vertex(" + value.toString + ")" } } </code></pre> <p>Since <code>Vertex</code> and <code>Graph</code> will be tied to one instance of <code>GraphKind</code>, then <code>T</code> will be fixed to whatever it was defined for that instance. For example:</p> <pre><code>scala&gt; new SimpleGraphKind[Int] res0: SimpleGraphKind[Int] = SimpleGraphKind@1dd0fe7 scala&gt; new res0.GraphImpl res1: res0.GraphImpl = line10() scala&gt; res1.add(10) scala&gt; res1.add("abc") &lt;console&gt;:9: error: type mismatch; found : java.lang.String("abc") required: Int res1.add("abc") ^ </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload