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
+34-25Lines changed: 34 additions & 25 deletions
Original file line number
Diff line number
Diff line change
@@ -9,40 +9,49 @@ 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 `A` as type parameter identifier, though any parameter name may be used.
17
18
```tut
18
-
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 }
19
+
class Stack[A] {
20
+
private var elements: List[A] = Nil
21
+
def push(x: A) { elements = x :: elements }
22
+
def peek: A = elements.head
23
+
def pop(): A = {
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 `A` as a parameter. This means the underlying list, `var elements: List[A] = Nil`, can only store elements of type `A`. The procedure `def push` only accepts objects of type `A` (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.
27
-
28
-
Here are some usage examples:
32
+
## Usage
29
33
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
-
}
34
+
To use a generic class, put the type in the square brackets in place of `A`.
39
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
+
```
42
+
The instance `stack` can only take Ints. However, if the type argument had subtypes, those could be passed in:
43
+
```
44
+
class Fruit
45
+
class Apple extends Fruit
46
+
class Banana extends Fruit
40
47
41
-
The output of this program will be:
48
+
val stack = new Stack[Fruit]
49
+
val apple = new Apple
50
+
val banana = new Banana
42
51
52
+
stack.push(apple)
53
+
stack.push(banana)
43
54
```
44
-
97
45
-
1
46
-
```
55
+
Class `Apple` and `Banana` both extend `Fruit` so we can push instances `apple` and `banana` onto the stack of `Fruit`.
47
56
48
-
_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._
57
+
_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[A]` is only a subtype of `Stack[B]` if and only if `B = A`. 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