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
Copy file name to clipboardExpand all lines: tutorials/tour/_posts/2017-02-13-generic-classes.md
+32-22Lines changed: 32 additions & 22 deletions
Original file line number
Diff line number
Diff line change
@@ -9,40 +9,50 @@ categories: tour
9
9
num: 18
10
10
next-page: variances
11
11
previous-page: sequence-comprehensions
12
+
assumed-knowledge: classes unified-types
12
13
---
14
+
Generic classes are classes which take a type as a parameter. They are particularly useful for collection classes.
13
15
14
-
Like in Java 5 (aka. [JDK 1.5](http://java.sun.com/j2se/1.5/)), Scala has built-in support for classes parameterized with types. Such generic classes are particularly useful for the development of collection classes.
15
-
Here is an example which demonstrates this:
16
-
16
+
## Defining a generic class
17
+
Generic classes take a type as a parameter within square brackets `[]`. One convention is to use the letter `T` as type parameter identifier, though this is not required.
17
18
```tut
18
19
class Stack[T] {
19
-
var elems: List[T] = Nil
20
-
def push(x: T) { elems = x :: elems }
21
-
def top: T = elems.head
22
-
def pop() { elems = elems.tail }
20
+
private var elements: List[T] = Nil
21
+
def push(x: T) { elements = x :: elements }
22
+
def peek: T = elements.head
23
+
def pop(): T = {
24
+
val currentTop = peek
25
+
elements = elements.tail
26
+
currentTop
27
+
}
23
28
}
24
29
```
30
+
This implementation of a `Stack` class takes any type `T` as a parameter. This means the underlying list, `var elements: List[T] = Nil`, can only store elements of type `T`. The procedure `def push` only accepts objects of type `T` (note: `elements = x :: elements` reassigns `elements` to a new list created by prepending `x` to the current `elements`).
25
31
26
-
Class `Stack` models imperative (mutable) stacks of an arbitrary element type `T`. The type parameters enforces that only legal elements (that are of type `T`) are pushed onto the stack. Similarly, with type parameters we can express that method `top` will only yield elements of the given type.
32
+
## Usage
27
33
28
-
Here are some usage examples:
34
+
To use a generic class, put the type in the square brackets in place of `T`.
35
+
```
36
+
val stack = new Stack[Int]
37
+
stack.push(1)
38
+
stack.push(2)
39
+
println(stack.pop) // prints 2
40
+
println(stack.pop) // prints 1
41
+
```
29
42
30
-
```tut
31
-
object GenericsTest extends App {
32
-
val stack = new Stack[Int]
33
-
stack.push(1)
34
-
stack.push('a')
35
-
println(stack.top)
36
-
stack.pop()
37
-
println(stack.top)
38
-
}
43
+
This Stack class can accept subtypes of the type argument:
39
44
```
45
+
class Fruit
46
+
class Apple extends Fruit
47
+
class Banana extends Fruit
40
48
41
-
The output of this program will be:
49
+
val stack = new Stack[Fruit]
50
+
val apple = new Apple
51
+
val banana = new Banana
42
52
53
+
stack.push(apple)
54
+
stack.push(banana)
43
55
```
44
-
97
45
-
1
46
-
```
56
+
Class `Apple` and `Banana` both extend `Fruit` so we can push instances `apple` and `banana` onto the stack of `Fruit`.
47
57
48
58
_Note: subtyping of generic types is *invariant*. This means that if we have a stack of characters of type `Stack[Char]` then it cannot be used as an integer stack of type `Stack[Int]`. This would be unsound because it would enable us to enter true integers into the character stack. To conclude, `Stack[T]` is only a subtype of `Stack[S]` if and only if `S = T`. Since this can be quite restrictive, Scala offers a [type parameter annotation mechanism](variances.html) to control the subtyping behavior of generic types._
0 commit comments