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
Self-types are a way to declare that a trait must be mixed into another trait, even though it doesn't directly extend it. That makes the members of the dependency available without imports.
Copy file name to clipboardExpand all lines: tutorials/tour/_posts/2017-02-13-traits.md
+36Lines changed: 36 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -22,6 +22,7 @@ trait HairColor
22
22
```
23
23
24
24
Traits become especially useful as generic types and with abstract methods.
25
+
25
26
```tut
26
27
trait Iterator[A] {
27
28
def hasNext: Boolean
@@ -33,6 +34,7 @@ Extending the `trait Iterator[A]` requires a type `A` and implementations of the
33
34
34
35
## Using traits
35
36
Use the `extends` keyword to extend a trait. Then implement any abstract members of the trait using the `override` keyword:
37
+
36
38
```tut
37
39
trait Iterator[A] {
38
40
def hasNext: Boolean
@@ -56,11 +58,13 @@ class IntIterator(to: Int) extends Iterator[Int] {
56
58
val iterator = new IntIterator(10)
57
59
iterator.next() // prints 0
58
60
iterator.next() // prints 1
61
+
59
62
```
60
63
This `IntIterator` class takes a parameter `to` as an upper bound. It `extends Iterator[Int]` which means that the `next` method must return an Int.
61
64
62
65
## Subtyping
63
66
Subtypes of traits can be used where a the trait is required.
67
+
64
68
```tut
65
69
import scala.collection.mutable.ArrayBuffer
66
70
@@ -79,4 +83,36 @@ animals.append(dog)
79
83
animals.append(cat)
80
84
animals.foreach(pet => println(pet.name)) // Prints Harry Sally
81
85
```
86
+
82
87
The `trait Pet` has an abstract field `name` which gets implemented by Cat and Dog in their constructors. On the last line, we call `pet.name` which must be implemented in any subtype of the trait `Pet`.
88
+
89
+
## Compound Types
90
+
91
+
Sometimes it is necessary to have parameter has multiple supertypes. In Scala this can be expressed with the help of _compound types_, which are intersections of object types.
92
+
93
+
Suppose we have two traits `Cloneable` and `Resetable`:
94
+
95
+
```tut
96
+
trait Cloneable extends java.lang.Cloneable {
97
+
override def clone(): Cloneable = {
98
+
super.clone().asInstanceOf[Cloneable]
99
+
}
100
+
}
101
+
trait Resetable {
102
+
def reset: Unit
103
+
}
104
+
```
105
+
106
+
Now suppose we want to write a function `cloneAndReset` which takes an object, clones it and resets the original object. We use the keyword `with` to specify that the object must be a subtype of both types.
107
+
108
+
```
109
+
def cloneAndReset(obj: Cloneable with Resetable): Cloneable = {
110
+
val cloned = obj.clone()
111
+
obj.reset
112
+
cloned
113
+
}
114
+
```
115
+
116
+
Because the type of `obj` is `Cloneable with Resetable`, we know the object has both a `clone` and a `reset` method.
117
+
118
+
Compound types can consist of several object types. The general form is: `A with B with C ...`.
0 commit comments