You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In Scala it is possible to let classes have other classes as members. Opposed to Java-like languages where such inner classes are members of the enclosing class, in Scala such inner classes are bound to the outer object. To illustrate the difference, we quickly sketch the implementation of a graph datatype:
15
-
15
+
16
16
```tut
17
17
class Graph {
18
18
class Node {
@@ -31,50 +31,32 @@ class Graph {
31
31
}
32
32
}
33
33
```
34
-
35
-
In our program, graphs are represented by a list of nodes. Nodes are objects of inner class `Node`. Each node has a list of neighbours, which get stored in the list `connectedNodes`. Now we can set up a graph with some nodes and connect the nodes incrementally:
36
-
37
-
```tut
38
-
object GraphTest extends App {
39
-
val g = new Graph
40
-
val n1 = g.newNode
41
-
val n2 = g.newNode
42
-
val n3 = g.newNode
43
-
n1.connectTo(n2)
44
-
n3.connectTo(n1)
45
-
}
46
-
```
47
-
48
-
We now enrich the above example with types to state explicitly what the type of the various defined entities is:
49
-
34
+
This program represents a graph as a list of nodes (`var nodes`). Each node knows which other nodes it's connected to (`connectedNodes`). The `class Node` is a _path-dependent type_ because it is nested in the `class Graph`. Therefore, everything in the `connectedNodes` must be created using the class attached to Graph.
35
+
50
36
```tut
51
-
object GraphTest extends App {
52
-
val g: Graph = new Graph
53
-
val n1: g.Node = g.newNode
54
-
val n2: g.Node = g.newNode
55
-
val n3: g.Node = g.newNode
56
-
n1.connectTo(n2)
57
-
n3.connectTo(n1)
58
-
}
37
+
val graph1: Graph = new Graph
38
+
val node1: graph1.Node = graph1.newNode
39
+
val node2: graph1.Node = graph1.newNode
40
+
val node3: graph1.Node = graph1.newNode
41
+
node1.connectTo(node2)
42
+
node3.connectTo(node1)
59
43
```
60
-
61
-
This code clearly shows that a node type is prefixed with its outer instance (which is object `g` in our example). If we now have two graphs, the type system of Scala does not allow us to mix nodes defined within one graph with the nodes of another graph, since the nodes of the other graph have a different type.
44
+
Notice how the type of all of the nodes is `graph1.Node`. This is because when we call `graph1.newNode` which calls `new Node`, the method is using the instance of `Node` specific to the instance `graph1`.
45
+
46
+
If we now have two graphs, the type system of Scala does not allow us to mix nodes defined within one graph with the nodes of another graph, since the nodes of the other graph have a different type.
62
47
Here is an illegal program:
63
-
64
-
```tut:fail
65
-
object IllegalGraphTest extends App {
66
-
val g: Graph = new Graph
67
-
val n1: g.Node = g.newNode
68
-
val n2: g.Node = g.newNode
69
-
n1.connectTo(n2) // legal
70
-
val h: Graph = new Graph
71
-
val n3: h.Node = h.newNode
72
-
n1.connectTo(n3) // illegal!
73
-
}
48
+
49
+
```tut
50
+
val graph1: Graph = new Graph
51
+
val node1: graph1.Node = graph1.newNode
52
+
val node2: graph1.Node = graph1.newNode
53
+
node1.connectTo(node2) // legal
54
+
val graph2: Graph = new Graph
55
+
val node3: graph2.Node = graph2.newNode
56
+
node1.connectTo(node3) // illegal!
74
57
```
75
-
76
-
Please note that in Java the last line in the previous example program would have been correct. For nodes of both graphs, Java would assign the same type `Graph.Node`; i.e. `Node` is prefixed with class `Graph`. In Scala such a type can be expressed as well, it is written `Graph#Node`. If we want to be able to connect nodes of different graphs, we have to change the definition of our initial graph implementation in the following way:
77
-
58
+
The type `graph1.Node` is distinct from the type `graph2.Node`. In Java, the last line in the previous example program would have been correct. For nodes of both graphs, Java would assign the same type `Graph.Node`; i.e. `Node` is prefixed with class `Graph`. In Scala such a type can be expressed as well, it is written `Graph#Node`. If we want to be able to connect nodes of different graphs, we have to change the definition of our initial graph implementation in the following way:
59
+
78
60
```tut
79
61
class Graph {
80
62
class Node {
@@ -93,5 +75,5 @@ class Graph {
93
75
}
94
76
}
95
77
```
96
-
97
-
> Please note that this program doesn't allow us to attach a node to two different graphs. If we want to remove this restriction as well, we have to change the type of variable nodes to `Graph#Node`.
78
+
79
+
> Note that this program doesn't allow us to attach a node to two different graphs. If we want to remove this restriction as well, we have to change the type of variable nodes to `Graph#Node`.
0 commit comments