1

共分散を確保するには、次の 3 つの方法があります。

  1. 純粋な共分散: Eiffel 言語を使用して、
  2. 共分散のシミュレーション: キャストとオーバーロードの使用
  3. F-bounded 多態性 OR 仮想型の使用

したがって、次の例で scala Abstract 型を使用して、仮想型でソリューションをテストしています。

  • 3 つの抽象クラスを定義します: Graph、Node、Edge
  • Graph クラスは 2 つのメソッドを定義します: attachNode(Node) と detachNode(Node)
  • Node クラスは 2 つのメソッドを定義します: attachToGraph(Graph) と detachFromGraph()

継承を使用して、異なるドメインに対して異なるサブクラスを作成します。

  • ネットワークの場合: class Network extends Graph、およびclass Host extends Node..
  • 化学の場合: class Molecule extends Graph、およびclass Atom extends Node、..
  • ...

唯一の制約は、たとえば Atom をネットワークに接続することによって「キメラ」を作成しないようにすることです。したがって、モデルは比較的単純です。

abstract class Graph {
  type CompatibleNode <: Node
  protected var myNodes = new ArrayBuffer[CompatibleNode]()

  def attachNode(node : compatibleNode) = {
      .... 

      // Inform the node about the attachement so it can do update
      node.attachToGraph(this)

      // save the node
      myNodes += node
  }
}

abstract class Node {
  type CompatibleGraph >: scala.Null <: Graph
  protected var myGraph : CompatibleGraph = null

  def attachToGraph(graph : compatibleGraph) = {
      .... 

      // Inform the graph about the attachement so it can do update
      graph.attachNode(this)

      // save the node
      myGraph = graph
  }
}

そして、特別なグラフを作成した後は、仮想タイプをオーバーライドするだけです:

class Network extends Graph { override type CompatibleNode = Host}
class Host extends Node { override type CompatibleGraph = Network}

class Molecule extends Graph { override type CompatibleNode = Atom}
class Atom extends Node { override type CompatibleGraph = Molecule}

これはうまくいくはずです(NIT言語で動作します)しかし、別のエラーがありました:

  • まず、graph.attachNode(this)この requiered graph.CompatibleNode、 found :を呼び出すときに型が一致しGraphないので、これをキャストします。

    graph.attachNode(this.asInstanceOf[graph.CompatibleNode])

NIT 言語は暗黙的にキャストすることに注意してください。

  • 次に、detachFromGraph() メソッドの場合:

    クラス ノード {

    ...
    
    def detachFromGraph() = {
    
         ....
    
         // inform my graph 
         myGraph.detachNode(this.asInstanceOf[myGraph.CompatibleNode])
    
         ...
     }
    

    }

私はエラーを受け取りました:myGraph.compatibleNode : requiered stable identifier、仕様を検索して読んだ後、次のことがわかりました:->安定した識別子は識別子で終わるパスです->パスであり、安定したメンバーであるp.x場合->安定したメンバーは.. ... または非揮発性型の値定義 -> 揮発性型: 型パラメーターまたは抽象型、....px

簡単に言えば、 path で抽象型のオブジェクトを使用できないのはなぜですか? 知らない!

そのため、提案がある場合、または scala 抽象型を仮想型として使用できる場合でも。

4

2 に答える 2

1

これは機能します(そして無限ループも削除されます)。パッケージは、パッケージのプライベート メソッドを説明できるようにするためのものです。

package foo {
  abstract class Graph {
    type CompatibleNode <: Node
    protected var myNodes = new ArrayBuffer[CompatibleNode]()

    def attachNode(node: CompatibleNode)
                  (implicit ev: this.type <:< node.CompatibleGraph) {

      // Inform the node about the attachement so it can do update
      node.backAttach(ev(this))

      // save the node
      myNodes += node
    }

    private[foo] def backAttach(node: CompatibleNode) { myNodes += node }
  }

  abstract class Node {
    type CompatibleGraph >: scala.Null <: Graph
    protected var myGraph: CompatibleGraph = null

    def attachToGraph(graph: CompatibleGraph)
                     (implicit ev: this.type <:< graph.CompatibleNode) {

      // Inform the graph about the attachement so it can do update
      graph.backAttach(ev(this))

      // save the node
      myGraph = graph
    }

    private[foo] def backAttach(graph: CompatibleGraph) { myGraph = graph }
  }
}

今:

class Network extends foo.Graph { override type CompatibleNode = Host}
class Host extends foo.Node { override type CompatibleGraph = Network}

class Molecule extends foo.Graph { override type CompatibleNode = Atom}
class Atom extends foo.Node { override type CompatibleGraph = Molecule}

そして試してみてください:

object GraphTest {
  val n = new Network()
  val h = new Host()

  n.attachNode(h)

  val a = new Atom()

  n.attachNode(a) // fails: type mismatch;
  // found : Atom required: GraphTest.n.CompatibleNode (which expands to) Host
}
于 2013-05-20T17:35:34.060 に答える
0

回避策は次のとおりです。

  def detachFromGraph () {
      detachFromThisGraph (myGraph)
  }

  def detachFromThisGraph (graph : CompatibleGraph) {
      graph.detachNode(this.asInstanceOf[graph.CompatibleNode])
  }

安定した識別子が何であるか、またはなぜここで必要なのか、私には少しもわかりません。

于 2012-05-02T15:42:27.783 に答える