Skip to content

Commit 11f1bb5

Browse files
authored
Merge pull request #2524 from flomebul/patch-1
Add code tabs for _tour/mixin-class-composition
2 parents f256b1e + 136ed9d commit 11f1bb5

File tree

1 file changed

+93
-0
lines changed

1 file changed

+93
-0
lines changed

Diff for: _tour/mixin-class-composition.md

+93
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ redirect_from: "/tutorials/tour/mixin-class-composition.html"
1212
---
1313
Mixins are traits which are used to compose a class.
1414

15+
{% tabs mixin-first-exemple class=tabs-scala-version %}
16+
17+
{% tab 'Scala 2' for=mixin-first-exemple %}
1518
```scala mdoc
1619
abstract class A {
1720
val message: String
@@ -30,19 +33,60 @@ println(d.loudMessage) // I'M AN INSTANCE OF CLASS B
3033
```
3134
Class `D` has a superclass `B` and a mixin `C`. Classes can only have one superclass but many mixins (using the keywords `extends` and `with` respectively). The mixins and the superclass may have the same supertype.
3235

36+
{% endtab %}
37+
38+
{% tab 'Scala 3' for=mixin-first-exemple %}
39+
```scala
40+
abstract class A:
41+
val message: String
42+
class B extends A:
43+
val message = "I'm an instance of class B"
44+
trait C extends A:
45+
def loudMessage = message.toUpperCase()
46+
class D extends B, C
47+
48+
val d = D()
49+
println(d.message) // I'm an instance of class B
50+
println(d.loudMessage) // I'M AN INSTANCE OF CLASS B
51+
```
52+
Class `D` has a superclass `B` and a mixin `C`. Classes can only have one superclass but many mixins (using the keyword `extends` and the separator `,` respectively). The mixins and the superclass may have the same supertype.
53+
54+
{% endtab %}
55+
56+
{% endtabs %}
57+
3358
Now let's look at a more interesting example starting with an abstract class:
3459

60+
{% tabs mixin-abstract-iterator class=tabs-scala-version %}
61+
62+
{% tab 'Scala 2' for=mixin-abstract-iterator %}
3563
```scala mdoc
3664
abstract class AbsIterator {
3765
type T
3866
def hasNext: Boolean
3967
def next(): T
4068
}
4169
```
70+
{% endtab %}
71+
72+
{% tab 'Scala 3' for=mixin-abstract-iterator %}
73+
```scala
74+
abstract class AbsIterator:
75+
type T
76+
def hasNext: Boolean
77+
def next(): T
78+
```
79+
{% endtab %}
80+
81+
{% endtabs %}
82+
4283
The class has an abstract type `T` and the standard iterator methods.
4384

4485
Next, we'll implement a concrete class (all abstract members `T`, `hasNext`, and `next` have implementations):
4586

87+
{% tabs mixin-concrete-string-iterator class=tabs-scala-version %}
88+
89+
{% tab 'Scala 2' for=mixin-concrete-string-iterator %}
4690
```scala mdoc
4791
class StringIterator(s: String) extends AbsIterator {
4892
type T = Char
@@ -55,24 +99,73 @@ class StringIterator(s: String) extends AbsIterator {
5599
}
56100
}
57101
```
102+
{% endtab %}
103+
104+
{% tab 'Scala 3' for=mixin-concrete-string-iterator %}
105+
```scala
106+
class StringIterator(s: String) extends AbsIterator:
107+
type T = Char
108+
private var i = 0
109+
def hasNext = i < s.length
110+
def next() =
111+
val ch = s charAt i
112+
i += 1
113+
ch
114+
```
115+
{% endtab %}
116+
117+
{% endtabs %}
118+
58119
`StringIterator` takes a `String` and can be used to iterate over the String (e.g. to see if a String contains a certain character).
59120

60121
Now let's create a trait which also extends `AbsIterator`.
61122

123+
{% tabs mixin-extended-abstract-iterator class=tabs-scala-version %}
124+
125+
{% tab 'Scala 2' for=mixin-extended-abstract-iterator %}
62126
```scala mdoc
63127
trait RichIterator extends AbsIterator {
64128
def foreach(f: T => Unit): Unit = while (hasNext) f(next())
65129
}
66130
```
67131
This trait implements `foreach` by continually calling the provided function `f: T => Unit` on the next element (`next()`) as long as there are further elements (`while (hasNext)`). Because `RichIterator` is a trait, it doesn't need to implement the abstract members of AbsIterator.
68132

133+
{% endtab %}
134+
135+
{% tab 'Scala 3' for=mixin-extended-abstract-iterator %}
136+
```scala
137+
trait RichIterator extends AbsIterator:
138+
def foreach(f: T => Unit): Unit = while hasNext do f(next())
139+
}
140+
```
141+
This trait implements `foreach` by continually calling the provided function `f: T => Unit` on the next element (`next()`) as long as there are further elements (`while hasNext`). Because `RichIterator` is a trait, it doesn't need to implement the abstract members of AbsIterator.
142+
143+
{% endtab %}
144+
145+
{% endtabs %}
146+
69147
We would like to combine the functionality of `StringIterator` and `RichIterator` into a single class.
70148

149+
{% tabs mixin-combination-class class=tabs-scala-version %}
150+
151+
{% tab 'Scala 2' for=mixin-combination-class %}
71152
```scala mdoc
72153
class RichStringIter extends StringIterator("Scala") with RichIterator
73154
val richStringIter = new RichStringIter
74155
richStringIter.foreach(println)
75156
```
157+
{% endtab %}
158+
159+
{% tab 'Scala 3' for=mixin-combination-class %}
160+
```scala
161+
class RichStringIter extends StringIterator("Scala"), RichIterator
162+
val richStringIter = RichStringIter()
163+
richStringIter.foreach(println)
164+
```
165+
{% endtab %}
166+
167+
{% endtabs %}
168+
76169
The new class `RichStringIter` has `StringIterator` as a superclass and `RichIterator` as a mixin.
77170

78171
With single inheritance we would not be able to achieve this level of flexibility.

0 commit comments

Comments
 (0)