From 5239edcbff73733afd48052cbff0436f24779d21 Mon Sep 17 00:00:00 2001 From: Travis Lee Date: Fri, 17 Mar 2017 19:41:12 +0100 Subject: [PATCH] Fixed broken link closes #771 --- .../2017-02-13-mixin-class-composition.md | 82 ++++++++++++------- 1 file changed, 54 insertions(+), 28 deletions(-) diff --git a/tutorials/tour/_posts/2017-02-13-mixin-class-composition.md b/tutorials/tour/_posts/2017-02-13-mixin-class-composition.md index 6fd5dd2cbc..7257a9fd86 100644 --- a/tutorials/tour/_posts/2017-02-13-mixin-class-composition.md +++ b/tutorials/tour/_posts/2017-02-13-mixin-class-composition.md @@ -1,18 +1,38 @@ --- layout: tutorial -title: Mixin Class Composition +title: Class Composition with Mixins disqus: true tutorial: scala-tour categories: tour num: 6 -next-page: anonymous-function-syntax +next-page: higher-order-functions previous-page: traits +prerequisite-knowledge: inheritance, traits, abstract-classes, unified-types --- +Mixins are traits which are used to compose a class. + +```tut +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 with C + +val d = new D +d.message // I'm an instance of class B +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. + +Now let's look at a more interesting example starting with an abstract class: -As opposed to languages that only support _single inheritance_, Scala has a more general notion of class reuse. Scala makes it possible to reuse the _new member definitions of a class_ (i.e. the delta in relationship to the superclass) in the definition of a new class. This is expressed as a _mixin-class composition_. Consider the following abstraction for iterators. - ```tut abstract class AbsIterator { type T @@ -20,36 +40,42 @@ abstract class AbsIterator { def next: T } ``` - -Next, consider a mixin class which extends `AbsIterator` with a method `foreach` which applies a given function to every element returned by the iterator. To define a class that can be used as a mixin we use the keyword `trait`. - -```tut -trait RichIterator extends AbsIterator { - def foreach(f: T => Unit) { while (hasNext) f(next) } -} -``` - -Here is a concrete iterator class, which returns successive characters of a given string: - +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): + ```tut 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 } + def hasNext = i < s.length + def next = { + val ch = s charAt i + i += 1 + ch + } } ``` - -We would like to combine the functionality of `StringIterator` and `RichIterator` into a single class. With single inheritance and interfaces alone this is impossible, as both classes contain member implementations with code. Scala comes to help with its _mixin-class composition_. It allows the programmers to reuse the delta of a class definition, i.e., all new definitions that are not inherited. This mechanism makes it possible to combine `StringIterator` with `RichIterator`, as is done in the following test program which prints a column of all the characters of a given string. - +`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`. + ```tut -object StringIteratorTest { - def main(args: Array[String]) { - class Iter extends StringIterator(args(0)) with RichIterator - val iter = new Iter - iter foreach println - } +trait RichIterator extends AbsIterator { + def foreach(f: T => Unit): Unit = while (hasNext) f(next) } ``` - -The `Iter` class in function `main` is constructed from a mixin composition of the parents `StringIterator` and `RichIterator` with the keyword `with`. The first parent is called the _superclass_ of `Iter`, whereas the second (and every other, if present) parent is called a _mixin_. +Because `RichIterator` is a trait, it doesn't need to implement the abstract members of AbsIterator. + +We would like to combine the functionality of `StringIterator` and `RichIterator` into a single class. + +```tut +object StringIteratorTest extends App { + class Iter extends StringIterator(args(0)) with RichIterator + val iter = new Iter + iter foreach println +} +``` +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.