20.scala的内部类

Posted 大数据群英萃

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了20.scala的内部类相关的知识,希望对你有一定的参考价值。

在Scala中,一个类可以作为另一个类的成员。 在一些类似 Java 的语言中,内部类是外部类的成员,而 Scala 正好相反,内部类是绑定到外部对象的。 假设我们希望编译器在编译时阻止我们混淆节点 nodes 与图形 graph 的关系,路径依赖类型提供了一种解决方案。

为了说明差异,我们简单描述了一个图形数据类型的实现:


class Graph { class Node { var connectedNodes: List[Node] = Nil def connectTo(node: Node) { if (!connectedNodes.exists(node.equals)) { connectedNodes = node :: connectedNodes } } } var nodes: List[Node] = Nil def newNode: Node = { val res = new Node nodes = res :: nodes res }}

该程序将图表示为节点列表 (List[Node])。 每个节点都有一个用来存储与其相连的其他节点的列表 (connectedNodes)。Node 是一个 路径依赖类型,因为它嵌套在类 Graph 中。 因此,connectedNodes 中存储的所有节点必须使用同一个 Graph 的实例对象的 newNode 方法来创建。


val graph1: Graph = new Graphval node1: graph1.Node = graph1.newNodeval node2: graph1.Node = graph1.newNodeval node3: graph1.Node = graph1.newNodenode1.connectTo(node2)node3.connectTo(node1)

为清楚起见,我们已经明确地将 node1node2,和 node3 的类型声明为graph1.Node,但编译器其实可以自动推断出它。 这是因为当我们通过调用 graph1.newNode 来调用 new Node 时,该方法产生特定于实例 graph1Node 类型的实例对象。

如果我们现在有两个图,Scala 的类型系统不允许我们将一个图形中定义的节点与另一个图的节点混合,因为另一个图形的节点具有不同的类型。下例是一个非法的程序:

val graph1: Graph = new Graphval node1: graph1.Node = graph1.newNodeval node2: graph1.Node = graph1.newNodenode1.connectTo(node2) val graph2: Graph = new Graphval node3: graph2.Node = graph2.newNodenode1.connectTo(node3) 

类型 graph1.Node 与类型 graph2.Node 完全不同。在 Java 中,上一个示例程序中的最后一行是正确的。对于两个图的节点,Java 将分配相同的类型 Graph.Node; 即 Node 以类 Graph 为前缀。在Scala中也可以表示出这种类型,它写成了 Graph#Node。如果我们希望能够连接不同图形的节点,我们必须通过以下方式更改图类的初始实现的定义:

class Graph { class Node { var connectedNodes: List[Graph#Node] = Nil def connectTo(node: Graph#Node) { if (!connectedNodes.exists(node.equals)) { connectedNodes = node :: connectedNodes } } } var nodes: List[Node] = Nil def newNode: Node = { val res = new Node nodes = res :: nodes res }}

推荐阅读:





以上是关于20.scala的内部类的主要内容,如果未能解决你的问题,请参考以下文章

错误:这个片段内部类应该是静态的 [ValidFragment]

为啥片段类应该是公开的?

片段 - 全局视图变量与本地和内部类侦听器和内存泄漏

ForegroundService没有从片段开始?

在内部片段类中使用ListView

自定义无内存泄漏的Handler内部类