Очень хорошим примером расширяемой структуры графа является
http://www.scala -lang.org / узел / 124
У тебя есть способы написать свой. Обратите внимание, что во всех случаях требовались некоторые изменения типа - то есть параметр типа GNode должен быть ковариантным, а ConcreteGraph должен быть написан как с отдельным классом узла, так и с типом, связанным для Node.
После этого первый способ написать dfs - это сделать его методом (он может быть окончательным, если вы хотите избежать накладных расходов на виртуальную диспетчеризацию).
trait GNode[+Graph] {
//... functions to get edges from this vertex, etc. ...
}
trait Graph {
type Node <: GNode[Graph]
def dfs(nodeAction : Node => Unit) = print("dfsing!")
}
class ConcreteGraph extends Graph {
class CGNode extends GNode[ConcreteGraph]
type Node <: CGNode
}
new ConcreteGraph dfs {node => println("foo")}
Второй, с dfs, а не методом, кажется, требует лишь немного дополнительных подсказок типа, чтобы использовать его.
def dfs[G <: Graph](graph : G, nodeAction : G#Node => Unit) = print("dfsing!")
dfs[ConcreteGraph](new ConcreteGraph, {node => println("foo")})
Третий путь - с карри. Из-за того, как работает вывод типов в Scala, на самом деле получается более чистый интерфейс
def dfs[G <: Graph](graph : G)(nodeAction : G#Node => Unit) = print("dfsing!")
dfs(new ConcreteGraph){node => println("foo")}