在Scala中,可以在类中拥有别的类作为其成员。与Java语言中内部类是包含它的类的成员相反,Scala中这些内部类是绑定在它的外部对象上的。如果想要在混合属于不同图的节点的时候,编译器能够在编译时阻止我们,那么路径依赖类型(Path-dependent types)提供了一种方案。
为了说明二者的区别,我们快速实现了图类型:
1 | class Graph { |
该程序表明图是节点的列表(List[Node]
)。每个节点拥有一个连接到其他节点(connectedNodes
)的列表。class Node
由于嵌套在class Graph
当中,因而是路径依赖类型。因此,connectedNodes
中的所有节点必须由Graph
的相同实例来使用newNode
进行创建。
1 | val graph1: Graph = new Graph |
这里我们显式地声明了node1
、node2
和node3
为graph1.Node
,其实编译器也能推断出来。因为我们在调用graph1.newNode
时,它调用了new Node
,该方法使用的其实是特定实例graph1
的node
实例。
如果我们有2个图,Scala的类型系统不允许我们把不同图的节点混合在一起,因为不同图的节点的类型是不一样的。
下面是错误示例:
1 | val graph1: Graph = new Graph |
graph1.Node
与graph2.Node
的类型是不同的。而在Java中,上面这段程序的最后一行是正确。对于不同图的节点来说,Java会分配相同的类型Graph.Node
(即类Graph
是Node
的前缀)。在Scala中这种类型可以被写作Graph#Node
。如果想要连接不同图的节点,我们需要按照下面的方式改变最开始对于图的实现:
1 | class Graph { |