2

このScalaチュートリアルは私を混乱させます。抽象型は、Nodeポリモーフィズムの従来の規則に従っていないようです...

type Node <: NodeIntf                // NodeIntf is assignable to Node.
abstract class NodeIntf {
  def connectWith(node: Node): Edge
}
class NodeImpl extends NodeIntf {
  def connectWith(node: Node): Edge = {
    val edge = newEdge(this, node)   // NodeImpl (this) is assignable to NodeIntf.
    edges = edge :: edges
    edge
  }
}
protected def newEdge(from: Node, to: Node): Edge

Node = NodeIntfとの場合NodeIntf = NodeImpl、なぜできないのですNode = NodeImplか?どうやら上記のコードはコンパイルされないので、私は尋ねます-なぜ「自己型参照」を使用する必要があるのですか?(チュートリアルを参照

4

2 に答える 2

7

の意味を逆にしました<:。ANodeはに割り当てることNodeIntfができます。つまり、次のようになります。

val x: NodeIntf = y: Node

さて、あなたが言うNode = NodeIntfと、さらに下にNodeIntf = NodeImpl、それは真実ではありません。Nodeはの任意のサブタイプでありNodeIntfNodeImplはの特定のサブタイプですNodeIntf

に関しては、、、、およびですが、Nodeそれはそれらの間の関係には意味がありません。両方とも、両方とものサブタイプであると言った方がよいでしょう。NodeIntfNodeImplNodeIntfNodeNodeImplAny

于 2013-02-15T13:12:53.173 に答える
3

まず、コードの一種の最小限の自己完結型バージョンを次に示します。

abstract class Graph {
  type Node <: NodeIntf

  case class Edge(s: Node, d: Node)

  abstract class NodeIntf {
    def connectWith(node: Node): Edge
  }

  class NodeImpl extends NodeIntf {
    def connectWith(node: Node): Edge = {
      val edge = newEdge(this, node)
      edge
    }
  }

  def newEdge(from: Node, to: Node): Edge = Edge(from, to)
}

あなたがそれをコンパイルしようとすると、あなたは得るでしょう

found   : NodeImpl.this.type (with underlying type Graph.this.NodeImpl)
required: Graph.this.Node
    val edge = newEdge(this, node)
                       ^

エラーメッセージの理由は、それNode抽象型であるためです。上界と下界NodeIntfがありますが、それでも抽象的です。つまり、抽象の実装は、の任意のサブタイプに自由Graphに設定/バインドできます。NodeNodeIntf

NodeImplコードでは、のインスタンスをに渡そうとします。newEdgeこれは、を期待しNodeます。あなたはNodeImplそのサブタイプですがNodeIntf、の実装は、それをのサブタイプにバインドすることによってさらにGraph制限することを決定する可能性があります。これにより、呼び出しが違法になります。NodeNodeImplnewEdge

すでにバインドNodeしている場合、たとえば、タイプエイリアスをNodeIntf

type Node = NodeIntf

その後、の実装はGraphバインドできなくなるため、上記のコードがコンパイルされNodeます。

于 2013-02-15T13:20:53.193 に答える