Code Examples for

Programming in Scala, Fifth Edition

Return to chapter index

11 Traits

Sample run of chapter's interpreter examples

11.1 How traits work


// In file traits/Philosophical.scala trait Philosophical: def philosophize = "I consume memory, therefore I am!"
class Frog extends Philosophical: override def toString = "green"
val frog = new Frog frog.philosophize // I consume memory, therefore I am!
val phil: Philosophical = frog phil.philosophize // I consume memory, therefore I am!
// In file traits/Ex1.scala class Animal class Frog extends Animal, Philosophical: override def toString = "green"
// In file traits/Frog.scala class Animal trait HasLegs class Frog extends Animal, Philosophical, HasLegs: override def toString = "green"
// In file traits/Ex2.scala class Animal class Frog extends Animal, Philosophical: override def toString = "green" override def philosophize = s"It ain't easy being $this!"
val phrog: Philosophical = new Frog phrog.philosophize // It ain't easy being green!

11.2 Thin versus rich interfaces


class Rational(n: Int, d: Int): // ... def < (that: Rational) = this.numer * that.denom < that.numer * this.denom def > (that: Rational) = that < this def <= (that: Rational) = (this < that) || (this == that) def >= (that: Rational) = (this > that) || (this == that)
// In file traits/Rational.scala class Rational(n: Int, d: Int) extends Ordered[Rational]: // ... def compare(that: Rational) = (this.numer * that.denom) - (that.numer * this.denom)
val half = new Rational(1, 2) val third = new Rational(1, 3) half < third // false half > third // true
// In file traits/Ex2.scala trait Ordered[T]: def compare(that: T): Int def <(that: T): Boolean = (this compare that) < 0 def >(that: T): Boolean = (this compare that) > 0 def <=(that: T): Boolean = (this compare that) <= 0 def >=(that: T): Boolean = (this compare that) >= 0

11.3 Traits as stackable modifications


// In file traits/IntQueue.scala abstract class IntQueue: def get(): Int def put(x: Int): Unit
// In file traits/BasicIntQueue.scala import scala.collection.mutable.ArrayBuffer class BasicIntQueue extends IntQueue: private val buf = ArrayBuffer.empty[Int] def get() = buf.remove(0) def put(x: Int) = buf += x
val queue = new BasicIntQueue queue.put(10) queue.put(20) queue.get() // 10 queue.get() // 20
// In file traits/Doubling.scala trait Doubling extends IntQueue: abstract override def put(x: Int) = super.put(2 * x)
class MyQueue extends BasicIntQueue, Doubling val queue = new MyQueue queue.put(10) queue.get() // 20
val queue = new BasicIntQueue with Doubling queue.put(10) queue.get() // 20
// In file traits/Incrementing.scala trait Incrementing extends IntQueue: abstract override def put(x: Int) = super.put(x + 1) trait Filtering extends IntQueue: abstract override def put(x: Int) = if x >= 0 then super.put(x)
val queue = new BasicIntQueue with Incrementing with Filtering queue.put(-1) queue.put(0) queue.put(1) queue.get() // 1 queue.get() // 2
val queue = new BasicIntQueue with Filtering with Incrementing queue.put(-1) queue.put(0) queue.put(1) queue.get() // 0 queue.get() // 1 queue.get() // 2

11.4 Why not multiple inheritance?


// In file traits/Ex2.scala // Multiple inheritance thought experiment val q = new BasicIntQueue with Incrementing with Doubling q.put(42) // which put would be called?
// Multiple inheritance thought experiment trait MyQueue extends BasicIntQueue, Incrementing, Doubling: def put(x: Int) = super[Incrementing].put(x) // (this is rarely used, super[Doubling].put(x) // but valid Scala)
// In file traits/Ex3.scala class Animal trait Furry extends Animal trait HasLegs extends Animal trait FourLegged extends HasLegs class Cat extends Animal, Furry, FourLegged

11.5 Trait parameters


trait Philosophical(message: String): def philosophize = message
class Frog extends Animal, Philosophical("I croak, therefore I am!") class Duck extends Animal, Philosophical("I quack, therefore I am!")
val frog = new Frog frog.philosophize // I croak, therefore I am! val duck = new Duck duck.philosophize // I quack, therefore I am!
class ProfoundAnimal extends Animal, Philosophical("In the beginning was the deed.")
class Frog extends ProfoundAnimal, Philosophical
val frog = new Frog frog.philosophize // In the beginning was the deed.
trait PhilosophicalAnimal extends Animal with Philosophical
// Does not compile class Frog extends PhilosophicalAnimal( "I croak, therefore I am!")
class Frog extends Philosophical("I croak, therefore I am!"), PhilosophicalAnimal
class Frog extends PhilosophicalAnimal, Philosophical("I croak, therefore I am!")

11.6 Conclusion

For more information about Programming in Scala, Fifth Edition (the "Stairway Book"), please visit:

http://www.artima.com/shop/programming_in_scala_5ed

and:

http://booksites.artima.com/programming_in_scala_5ed

Copyright © 2007-2020 Artima, Inc. All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.