Skip to content

Commit d4e3606

Browse files
committed
Add code tabs for _tour/abstract-types
1 parent de06e87 commit d4e3606

File tree

1 file changed

+66
-1
lines changed

1 file changed

+66
-1
lines changed

_tour/abstract-type-members.md

+66-1
Original file line numberDiff line numberDiff line change
@@ -17,31 +17,57 @@ Abstract types, such as traits and abstract classes, can in turn have abstract t
1717
This means that the concrete implementations define the actual types.
1818
Here's an example:
1919

20+
{% tabs abstract-types_1 class=tabs-scala-version %}
21+
{% tab 'Scala 2' for=abstract-types_1 %}
2022
```scala mdoc
2123
trait Buffer {
2224
type T
2325
val element: T
2426
}
2527
```
28+
{% endtab %}
29+
{% tab 'Scala 3' for=abstract-types_1 %}
30+
```scala
31+
trait Buffer:
32+
type T
33+
val element: T
34+
```
35+
{% endtab %}
36+
{% endtabs %}
37+
2638
Here we have defined an abstract `type T`. It is used to describe the type of `element`. We can extend this trait in an abstract class, adding an upper-type-bound to `T` to make it more specific.
2739

40+
{% tabs abstract-types_2 class=tabs-scala-version %}
41+
{% tab 'Scala 2' for=abstract-types_2 %}
2842
```scala mdoc
2943
abstract class SeqBuffer extends Buffer {
3044
type U
3145
type T <: Seq[U]
3246
def length = element.length
3347
}
3448
```
49+
{% endtab %}
50+
{% tab 'Scala 3' for=abstract-types_2 %}
51+
```scala
52+
abstract class SeqBuffer extends Buffer:
53+
type U
54+
type T <: Seq[U]
55+
def length = element.length
56+
```
57+
{% endtab %}
58+
{% endtabs %}
59+
3560
Notice how we can use yet another abstract type `U` in the specification of an upper-type-bound for `T`. This `class SeqBuffer` allows us to store only sequences in the buffer by stating that type `T` has to be a subtype of `Seq[U]` for a new abstract type `U`.
3661

3762
Traits or [classes](classes.html) with abstract type members are often used in combination with anonymous class instantiations. To illustrate this, we now look at a program which deals with a sequence buffer that refers to a list of integers:
3863

64+
{% tabs abstract-types_3 class=tabs-scala-version %}
65+
{% tab 'Scala 2' for=abstract-types_3 %}
3966
```scala mdoc
4067
abstract class IntSeqBuffer extends SeqBuffer {
4168
type U = Int
4269
}
4370

44-
4571
def newIntSeqBuf(elem1: Int, elem2: Int): IntSeqBuffer =
4672
new IntSeqBuffer {
4773
type T = List[U]
@@ -51,10 +77,30 @@ val buf = newIntSeqBuf(7, 8)
5177
println("length = " + buf.length)
5278
println("content = " + buf.element)
5379
```
80+
{% endtab %}
81+
{% tab 'Scala 3' for=abstract-types_3 %}
82+
```scala
83+
abstract class IntSeqBuffer extends SeqBuffer:
84+
type U = Int
85+
86+
def newIntSeqBuf(elem1: Int, elem2: Int): IntSeqBuffer =
87+
new IntSeqBuffer:
88+
type T = List[U]
89+
val element = List(elem1, elem2)
90+
91+
val buf = newIntSeqBuf(7, 8)
92+
println("length = " + buf.length)
93+
println("content = " + buf.element)
94+
```
95+
{% endtab %}
96+
{% endtabs %}
97+
5498
Here the factory `newIntSeqBuf` uses an anonymous class implementation of `IntSeqBuffer` (i.e. `new IntSeqBuffer`) to set the abstract type `T` to the concrete type `List[Int]`.
5599

56100
It is also possible to turn abstract type members into type parameters of classes and vice versa. Here is a version of the code above which only uses type parameters:
57101

102+
{% tabs abstract-types_4 class=tabs-scala-version %}
103+
{% tab 'Scala 2' for=abstract-types_4 %}
58104
```scala mdoc:nest
59105
abstract class Buffer[+T] {
60106
val element: T
@@ -72,5 +118,24 @@ val buf = newIntSeqBuf(7, 8)
72118
println("length = " + buf.length)
73119
println("content = " + buf.element)
74120
```
121+
{% endtab %}
122+
{% tab 'Scala 3' for=abstract-types_4 %}
123+
```scala
124+
abstract class Buffer[+T]:
125+
val element: T
126+
127+
abstract class SeqBuffer[U, +T <: Seq[U]] extends Buffer[T]:
128+
def length = element.length
129+
130+
def newIntSeqBuf(e1: Int, e2: Int): SeqBuffer[Int, Seq[Int]] =
131+
new SeqBuffer[Int, List[Int]]:
132+
val element = List(e1, e2)
133+
134+
val buf = newIntSeqBuf(7, 8)
135+
println("length = " + buf.length)
136+
println("content = " + buf.element)
137+
```
138+
{% endtab %}
139+
{% endtabs %}
75140

76141
Note that we have to use [variance annotations](variances.html) here (`+T <: Seq[U]`) in order to hide the concrete sequence implementation type of the object returned from method `newIntSeqBuf`. Furthermore, there are cases where it is not possible to replace abstract type members with type parameters.

0 commit comments

Comments
 (0)