Code Examples for

Programming in Scala, Fifth Edition

Return to chapter index

17 Scala's Hierarchy

Sample run of chapter's interpreter examples

17.1 Scala's class hierarchy


final def ==(that: Any): Boolean final def !=(that: Any): Boolean def equals(that: Any): Boolean def ##: Int def hashCode: Int def toString: String
scala> new Int
1 |new Int | ^^^ | Int is abstract; it cannot be instantiated
42.toString // 42 42.hashCode // 42 42.equals(42) // true
42.max(43) // 43 42.min(43) // 42 1 until 5 // Range 1 until 5 1 to 5 // Range 1 to 5 3.abs // 3 -3.abs // 3

17.2 How primitives are implemented


// In file scalas-hierarchy/Ex1.java // This is Java boolean isEqual(int x, int y) { return x == y; } System.out.println(isEqual(421, 421));
// In file scalas-hierarchy/Ex2.java // This is Java boolean isEqual(Integer x, Integer y) { return x == y; } System.out.println(isEqual(421, 421));
def isEqual(x: Int, y: Int) = x == y isEqual(421, 421) // true def isEqual(x: Any, y: Any) = x == y isEqual(421, 421) // true
val x = "abcd".substring(2) // cd val y = "abcd".substring(2) // cd x == y // true
val x = new String("abc") // abc val y = new String("abc") // abc x == y // true x eq y // false x ne y // true

17.3 Bottom types


scala> val i: Int = null 1 |val i: Int = null | ^^^^ | Found: Null | Required: Int
def error(message: String): Nothing = throw new RuntimeException(message)
// In file scalas-hierarchy/Ex3.scala def divide(x: Int, y: Int): Int = if y != 0 then x / y else sys.error("can't divide by zero")

17.4 Defining your own value classes


class Dollars(val amount: Int) extends AnyVal: override def toString = "$" + amount
val money = new Dollars(1_000_000) money.amount // 1000000
class SwissFrancs(val amount: Int) extends AnyVal: override def toString = s"$amount CHF"
scala> val dollars: Dollars = new SwissFrancs(1000) 1 |val dollars: Dollars = new SwissFrancs(1000) | ^^^^^^^^^^^^^^^^^^^^^ | Found: SwissFrancs | Required: Dollars
def title(text: String, anchor: String, style: String): String = s"<a id='$anchor'><h1 class='$style'>$text</h1></a>"
scala> title("chap:vcls", "bold", "Value Classes") val res17: String = <a id='bold'><h1 class='Value Classes'>chap:vcls</h1></a>
class Anchor(val value: String) extends AnyVal class Style(val value: String) extends AnyVal class Text(val value: String) extends AnyVal class Html(val value: String) extends AnyVal
def title(text: Text, anchor: Anchor, style: Style): Html = Html( s"<a id='${anchor.value}'>" + s"<h1 class='${style.value}'>" + text.value + "</h1></a>" )
scala> title(Anchor("chap:vcls"), Style("bold"), | Text("Value Classes")) 1 |title(new Anchor("chap:vcls"), new Style("bold"), | ^^^^^^^^^^^^^^^^^^^^^^^ | Found: Anchor | Required: Text 1 |title(Anchor("chap:vcls"), Style("bold"), | ^^^^^^^^^^^^^^ | Found: Style | Required: Anchor 2 | Text("Value Classes")) | ^^^^^^^^^^^^^^^^^^^^^^ | Found: Text | Required: Style

17.5 Intersection types


scala> val q = new BasicIntQueue with Incrementing with Filtering val q: BasicIntQueue & Incrementing & Filtering = anon$...
// Compiles because B \& I \& F <: I \& F val q2: Incrementing & Filtering = q // Compiles because I \& F is equivalent to F \& I val q3: Filtering & Incrementing = q2

17.6 Union types


trait Fruit trait Plum extends Fruit trait Apricot extends Fruit trait Pluot extends Plum, Apricot
val plumOrApricot: Plum | Apricot = new Plum {} // This compiles fine, because Plum | Apricot <: Fruit val fruit: Fruit = plumOrApricot // But you cannot use a Fruit where Plum | Apricot is needed scala> val doesNotCompile: Plum | Apricot = fruit 1 |val doesNotCompile: Plum | Apricot = fruit | ^^^^^ | Found: (fruit : Fruit) | Required: Plum | Apricot
val pluot: Pluot = new Pluot {} // This compiles fine, because Pluot <: Plum \& Apricot val plumAndApricot: Plum & Apricot = pluot // But you cannot use a Plum \& Apricot where Pluot is needed scala> val doesNotCompile: Pluot = plumAndApricot 1 |val doesNotCompile: Pluot = plumAndApricot | ^^^^^^^^^^^^^^ | Found: (plumAndApricot : Plum & Apricot) | Required: Pluot
def errorMessage(msg: Int | String): String = msg match case n: Int => s"Error number: ${n.abs}" case s: String => s + "!"
errorMessage("Oops") // "Oops!" errorMessage(-42) // "Error number: 42"

17.7 Transparent traits


scala> val q = new BasicIntQueue with | Incrementing with Filtering val q: BasicIntQueue & Incrementing & Filtering = anon$...
transparent trait Incrementing extends IntQueue: abstract override def put(x: Int) = super.put(x + 1) transparent trait Filtering extends IntQueue: abstract override def put(x: Int) = if x >= 0 then super.put(x)
scala> val q = new BasicIntQueue with | Incrementing with Filtering val q: BasicIntQueue = anon$...
scala> val q: BasicIntQueue & Incrementing & Filtering = | new BasicIntQueue with Incrementing with Filtering | val q: BasicIntQueue & Incrementing & Filtering = anon$...

17.8 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.