1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
|
trait Graph {
type Edge;
type Node <: NodeIntf;
trait NodeIntf {
def connectWith(node: Node): Edge;
}
def nodes: List[Node];
def edges: List[Edge];
def addNode: Node;
protected var ids = 0;
}
abstract class DirectedGraph extends Graph {
type Edge <: EdgeImpl;
class EdgeImpl(origin: Node, dest: Node) {
def from = origin;
def to = dest;
override def toString = ""+origin+" --> "+dest
}
class NodeImpl extends NodeIntf { self: Node =>
val id = ids
ids = ids + 1
def connectWith(node: Node): Edge = {
val edge = newEdge(this, node);
edges = edge :: edges;
edge;
}
override def toString = "Node "+id
}
protected def newNode: Node;
protected def newEdge(from: Node, to: Node): Edge;
var nodes: List[Node] = Nil;
var edges: List[Edge] = Nil;
def addNode: Node = {
val node = newNode;
nodes = node :: nodes;
node;
}
}
class ConcreteDirectedGraph extends DirectedGraph {
type Edge = EdgeImpl;
type Node = NodeImpl;
protected def newNode: Node = {
new NodeImpl;
}
protected def newEdge(f: Node, t: Node): Edge = {
new EdgeImpl(f, t);
}
}
object ExplicitThis {
def main(args: Array[String]): Unit = {
val g: Graph = new ConcreteDirectedGraph;
val n1 = g.addNode;
val n2 = g.addNode;
val n3 = g.addNode;
Console.println(n1.connectWith(n2))
Console.println(n2.connectWith(n3))
Console.println(n1.connectWith(n3))
}
}
|