From 813a57010db1bb134a868a3c939af9f259cbbcd5 Mon Sep 17 00:00:00 2001 From: Luc Henninger Date: Thu, 15 Sep 2022 10:27:11 +0200 Subject: [PATCH 1/6] Add code tabs for _tour/mixin-class-composition --- _tour/mixin-class-composition.md | 93 ++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/_tour/mixin-class-composition.md b/_tour/mixin-class-composition.md index fc362b2643..c084c09678 100644 --- a/_tour/mixin-class-composition.md +++ b/_tour/mixin-class-composition.md @@ -12,6 +12,9 @@ redirect_from: "/tutorials/tour/mixin-class-composition.html" --- Mixins are traits which are used to compose a class. +{% tabs mixin-first-exemple class=tabs-scala-version %} + +{% tab 'Scala 2' for=mixin-first-exemple %} ```scala mdoc abstract class A { val message: String @@ -30,8 +33,33 @@ println(d.loudMessage) // I'M AN INSTANCE OF CLASS B ``` 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. +{% endtab %} + +{% tab 'Scala 3' for=mixin-first-exemple %} +```scala mdoc +abstract class A: + val message: String +class B extends A: + val message = "I'm an instance of class B" +trait C extends A: + def loudMessage = message.toUpperCase() +class D extends B, C + +val d = D() +println(d.message) // I'm an instance of class B +println(d.loudMessage) // I'M AN INSTANCE OF CLASS B +``` +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. + +{% endtab %} + +{% endtabs %} + Now let's look at a more interesting example starting with an abstract class: +{% tabs mixin-abstract-iterator class=tabs-scala-version %} + +{% tab 'Scala 2' for=mixin-abstract-iterator %} ```scala mdoc abstract class AbsIterator { type T @@ -39,10 +67,26 @@ abstract class AbsIterator { def next(): T } ``` +{% endtab %} + +{% tab 'Scala 3' for=mixin-abstract-iterator %} +```scala mdoc +abstract class AbsIterator: + type T + def hasNext: Boolean + def next(): T +``` +{% endtab %} + +{% endtabs %} + The class has an abstract type `T` and the standard iterator methods. Next, we'll implement a concrete class (all abstract members `T`, `hasNext`, and `next` have implementations): +{% tabs mixin-concrete-string-iterator class=tabs-scala-version %} + +{% tab 'Scala 2' for=mixin-concrete-string-iterator %} ```scala mdoc class StringIterator(s: String) extends AbsIterator { type T = Char @@ -55,10 +99,30 @@ class StringIterator(s: String) extends AbsIterator { } } ``` +{% endtab %} + +{% tab 'Scala 3' for=mixin-concrete-string-iterator %} +```scala mdoc +class StringIterator(s: String) extends AbsIterator: + type T = Char + private var i = 0 + def hasNext = i < s.length + def next() = + val ch = s charAt i + i += 1 + ch +``` +{% endtab %} + +{% endtabs %} + `StringIterator` takes a `String` and can be used to iterate over the String (e.g. to see if a String contains a certain character). Now let's create a trait which also extends `AbsIterator`. +{% tabs mixin-extended-abstract-iterator class=tabs-scala-version %} + +{% tab 'Scala 2' for=mixin-extended-abstract-iterator %} ```scala mdoc trait RichIterator extends AbsIterator { def foreach(f: T => Unit): Unit = while (hasNext) f(next()) @@ -66,13 +130,42 @@ trait RichIterator extends AbsIterator { ``` 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. +{% endtab %} + +{% tab 'Scala 3' for=mixin-extended-abstract-iterator %} +```scala mdoc +trait RichIterator extends AbsIterator: + def foreach(f: T => Unit): Unit = while hasNext do f(next()) +} +``` +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. + +{% endtab %} + +{% endtabs %} + We would like to combine the functionality of `StringIterator` and `RichIterator` into a single class. +{% tabs mixin-combination-class class=tabs-scala-version %} + +{% tab 'Scala 2' for=mixin-combination-class %} ```scala mdoc class RichStringIter extends StringIterator("Scala") with RichIterator val richStringIter = new RichStringIter richStringIter.foreach(println) ``` +{% endtab %} + +{% tab 'Scala 3' for=mixin-combination-class %} +```scala mdoc +class RichStringIter extends StringIterator("Scala"), RichIterator +val richStringIter = RichStringIter() +richStringIter.foreach(println) +``` +{% endtab %} + +{% endtabs %} + The new class `RichStringIter` has `StringIterator` as a superclass and `RichIterator` as a mixin. With single inheritance we would not be able to achieve this level of flexibility. From 33a7d99abc24ffb6164f672952d2bf778377fe74 Mon Sep 17 00:00:00 2001 From: Luc Henninger Date: Thu, 15 Sep 2022 10:40:42 +0200 Subject: [PATCH 2/6] Update _tour/mixin-class-composition.md Co-authored-by: Jamie Thompson --- _tour/mixin-class-composition.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_tour/mixin-class-composition.md b/_tour/mixin-class-composition.md index c084c09678..2bbe8a6cc1 100644 --- a/_tour/mixin-class-composition.md +++ b/_tour/mixin-class-composition.md @@ -102,7 +102,7 @@ class StringIterator(s: String) extends AbsIterator { {% endtab %} {% tab 'Scala 3' for=mixin-concrete-string-iterator %} -```scala mdoc +```scala class StringIterator(s: String) extends AbsIterator: type T = Char private var i = 0 From cfb859f283162311e487599300510a1002154be6 Mon Sep 17 00:00:00 2001 From: Luc Henninger Date: Thu, 15 Sep 2022 10:40:54 +0200 Subject: [PATCH 3/6] Update _tour/mixin-class-composition.md Co-authored-by: Jamie Thompson --- _tour/mixin-class-composition.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_tour/mixin-class-composition.md b/_tour/mixin-class-composition.md index 2bbe8a6cc1..49eb39d27b 100644 --- a/_tour/mixin-class-composition.md +++ b/_tour/mixin-class-composition.md @@ -36,7 +36,7 @@ Class `D` has a superclass `B` and a mixin `C`. Classes can only have one superc {% endtab %} {% tab 'Scala 3' for=mixin-first-exemple %} -```scala mdoc +```scala abstract class A: val message: String class B extends A: From ed79c4e88c959d1e46b6fcb894790bb495fdc276 Mon Sep 17 00:00:00 2001 From: Luc Henninger Date: Thu, 15 Sep 2022 10:41:07 +0200 Subject: [PATCH 4/6] Update _tour/mixin-class-composition.md Co-authored-by: Jamie Thompson --- _tour/mixin-class-composition.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_tour/mixin-class-composition.md b/_tour/mixin-class-composition.md index 49eb39d27b..2d2215de3c 100644 --- a/_tour/mixin-class-composition.md +++ b/_tour/mixin-class-composition.md @@ -70,7 +70,7 @@ abstract class AbsIterator { {% endtab %} {% tab 'Scala 3' for=mixin-abstract-iterator %} -```scala mdoc +```scala abstract class AbsIterator: type T def hasNext: Boolean From abb28a0d79d82279c6d3e8abd7f795ab62f44e39 Mon Sep 17 00:00:00 2001 From: Luc Henninger Date: Thu, 15 Sep 2022 10:43:07 +0200 Subject: [PATCH 5/6] Update _tour/mixin-class-composition.md Co-authored-by: Jamie Thompson --- _tour/mixin-class-composition.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_tour/mixin-class-composition.md b/_tour/mixin-class-composition.md index 2d2215de3c..5afc0a26a9 100644 --- a/_tour/mixin-class-composition.md +++ b/_tour/mixin-class-composition.md @@ -133,7 +133,7 @@ This trait implements `foreach` by continually calling the provided function `f: {% endtab %} {% tab 'Scala 3' for=mixin-extended-abstract-iterator %} -```scala mdoc +```scala trait RichIterator extends AbsIterator: def foreach(f: T => Unit): Unit = while hasNext do f(next()) } From 136ed9d198819ae37208aad76243a8e4096ac132 Mon Sep 17 00:00:00 2001 From: Luc Henninger Date: Thu, 15 Sep 2022 10:43:33 +0200 Subject: [PATCH 6/6] Update _tour/mixin-class-composition.md Co-authored-by: Jamie Thompson --- _tour/mixin-class-composition.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_tour/mixin-class-composition.md b/_tour/mixin-class-composition.md index 5afc0a26a9..ee63462306 100644 --- a/_tour/mixin-class-composition.md +++ b/_tour/mixin-class-composition.md @@ -157,7 +157,7 @@ richStringIter.foreach(println) {% endtab %} {% tab 'Scala 3' for=mixin-combination-class %} -```scala mdoc +```scala class RichStringIter extends StringIterator("Scala"), RichIterator val richStringIter = RichStringIter() richStringIter.foreach(println)