object ObjectOrientedProgramming extends AnyFlatSpec with ScalaTutorialSection
- Alphabetic
- By Inheritance
- ObjectOrientedProgramming
- ScalaTutorialSection
- Section
- Matchers
- Explicitly
- MatcherWords
- Tolerance
- AnyFlatSpec
- AnyFlatSpecLike
- Documenting
- Alerting
- Notifying
- Informing
- CanVerb
- MustVerb
- ShouldVerb
- TestRegistration
- TestSuite
- Suite
- Serializable
- Assertions
- TripleEquals
- TripleEqualsSupport
- AnyRef
- Any
- Hide All
- Show All
- Public
- Protected
Type Members
- final class AWord extends AnyRef
- Definition Classes
- Matchers
- final class AnWord extends AnyRef
- Definition Classes
- Matchers
- sealed class AnyShouldWrapper[T] extends AnyRef
- Definition Classes
- Matchers
- final class BehaviorWord extends AnyRef
- Attributes
- protected
- Definition Classes
- AnyFlatSpecLike
- class CheckingEqualizer[L] extends AnyRef
- Definition Classes
- TripleEqualsSupport
- sealed class Collected extends Serializable
- Attributes
- protected
- Definition Classes
- Matchers
- class DecidedByEquality[A] extends Equality[A]
- Definition Classes
- Explicitly
- class DecidedWord extends AnyRef
- Definition Classes
- Explicitly
- class DeterminedByEquivalence[T] extends Equivalence[T]
- Definition Classes
- Explicitly
- class DeterminedWord extends AnyRef
- Definition Classes
- Explicitly
- class Equalizer[L] extends AnyRef
- Definition Classes
- TripleEqualsSupport
- final class HavePropertyMatcherGenerator extends AnyRef
- Definition Classes
- Matchers
- final class IgnoreVerbString extends AnyRef
- Attributes
- protected
- Definition Classes
- AnyFlatSpecLike
- final class IgnoreVerbStringTaggedAs extends AnyRef
- Attributes
- protected
- Definition Classes
- AnyFlatSpecLike
- final class IgnoreWord extends AnyRef
- Attributes
- protected
- Definition Classes
- AnyFlatSpecLike
- final class InAndIgnoreMethods extends AnyRef
- Attributes
- protected
- Definition Classes
- AnyFlatSpecLike
- final class InAndIgnoreMethodsAfterTaggedAs extends AnyRef
- Attributes
- protected
- Definition Classes
- AnyFlatSpecLike
- final class ItVerbString extends AnyRef
- Attributes
- protected
- Definition Classes
- AnyFlatSpecLike
- final class ItVerbStringTaggedAs extends AnyRef
- Attributes
- protected
- Definition Classes
- AnyFlatSpecLike
- final class ItWord extends AnyRef
- Attributes
- protected
- Definition Classes
- AnyFlatSpecLike
- final class KeyWord extends AnyRef
- Definition Classes
- Matchers
- trait NoArgTest extends () => Outcome with TestData
- Attributes
- protected
- Definition Classes
- TestSuite
- final class PlusOrMinusWrapper[T] extends AnyRef
- Definition Classes
- Tolerance
- final class RegexWord extends AnyRef
- Definition Classes
- Matchers
- final class RegexWrapper extends AnyRef
- Definition Classes
- Matchers
- class ResultOfBeWordForAny[T] extends AnyRef
- Definition Classes
- Matchers
- sealed class ResultOfBeWordForCollectedAny[T] extends AnyRef
- Definition Classes
- Matchers
- final class ResultOfBeWordForCollectedArray[T] extends ResultOfBeWordForCollectedAny[Array[T]]
- Definition Classes
- Matchers
- final class ResultOfCollectedAny[T] extends AnyRef
- Definition Classes
- Matchers
- final class ResultOfContainWordForCollectedAny[T] extends AnyRef
- Definition Classes
- Matchers
- final class ResultOfEndWithWordForCollectedString extends AnyRef
- Definition Classes
- Matchers
- final class ResultOfEndWithWordForString extends AnyRef
- Definition Classes
- Matchers
- final class ResultOfFullyMatchWordForCollectedString extends AnyRef
- Definition Classes
- Matchers
- final class ResultOfFullyMatchWordForString extends AnyRef
- Definition Classes
- Matchers
- final class ResultOfHaveWordForCollectedExtent[A] extends AnyRef
- Definition Classes
- Matchers
- final class ResultOfHaveWordForExtent[A] extends AnyRef
- Definition Classes
- Matchers
- final class ResultOfIncludeWordForCollectedString extends AnyRef
- Definition Classes
- Matchers
- final class ResultOfIncludeWordForString extends AnyRef
- Definition Classes
- Matchers
- final class ResultOfNotWordForCollectedAny[T] extends AnyRef
- Definition Classes
- Matchers
- final class ResultOfStartWithWordForCollectedString extends AnyRef
- Definition Classes
- Matchers
- final class ResultOfStartWithWordForString extends AnyRef
- Definition Classes
- Matchers
- trait StringCanWrapperForVerb extends AnyRef
- Definition Classes
- CanVerb
- trait StringMustWrapperForVerb extends AnyRef
- Definition Classes
- MustVerb
- final class StringShouldWrapper extends AnyShouldWrapper[String] with org.scalatest.matchers.should.Matchers.StringShouldWrapperForVerb
- Definition Classes
- Matchers
- trait StringShouldWrapperForVerb extends AnyRef
- Definition Classes
- ShouldVerb
- class TheAfterWord extends AnyRef
- Definition Classes
- Explicitly
- final class TheSameInstanceAsPhrase extends AnyRef
- Definition Classes
- Matchers
- final class TheyVerbString extends AnyRef
- Attributes
- protected
- Definition Classes
- AnyFlatSpecLike
- final class TheyVerbStringTaggedAs extends AnyRef
- Attributes
- protected
- Definition Classes
- AnyFlatSpecLike
- final class TheyWord extends AnyRef
- Attributes
- protected
- Definition Classes
- AnyFlatSpecLike
- final class ValueWord extends AnyRef
- Definition Classes
- Matchers
Value Members
- final def !=(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
- def !==[T](right: Spread[T]): TripleEqualsInvocationOnSpread[T]
- Definition Classes
- TripleEqualsSupport
- def !==(right: Null): TripleEqualsInvocation[Null]
- Definition Classes
- TripleEqualsSupport
- def !==[T](right: T): TripleEqualsInvocation[T]
- Definition Classes
- TripleEqualsSupport
- final def ##: Int
- Definition Classes
- AnyRef → Any
- def <[T](right: T)(implicit arg0: Ordering[T]): ResultOfLessThanComparison[T]
- Definition Classes
- Matchers
- def <=[T](right: T)(implicit arg0: Ordering[T]): ResultOfLessThanOrEqualToComparison[T]
- Definition Classes
- Matchers
- final def ==(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
- def ===[T](right: Spread[T]): TripleEqualsInvocationOnSpread[T]
- Definition Classes
- TripleEqualsSupport
- def ===(right: Null): TripleEqualsInvocation[Null]
- Definition Classes
- TripleEqualsSupport
- def ===[T](right: T): TripleEqualsInvocation[T]
- Definition Classes
- TripleEqualsSupport
- def >[T](right: T)(implicit arg0: Ordering[T]): ResultOfGreaterThanComparison[T]
- Definition Classes
- Matchers
- def >=[T](right: T)(implicit arg0: Ordering[T]): ResultOfGreaterThanOrEqualToComparison[T]
- Definition Classes
- Matchers
- def a[T](implicit arg0: ClassTag[T]): ResultOfATypeInvocation[T]
- Definition Classes
- Matchers
- val a: AWord
- Definition Classes
- Matchers
- val after: TheAfterWord
- Definition Classes
- Explicitly
- def alert: Alerter
- Attributes
- protected
- Definition Classes
- AnyFlatSpecLike → Alerting
- def all(xs: String)(implicit collecting: Collecting[Char, String], prettifier: Prettifier, pos: Position): ResultOfCollectedAny[Char]
- Definition Classes
- Matchers
- def all[K, V, JMAP[k, v] <: Map[k, v]](xs: JMAP[K, V])(implicit collecting: Collecting[Entry[K, V], JMAP[K, V]], prettifier: Prettifier, pos: Position): ResultOfCollectedAny[Entry[K, V]]
- Definition Classes
- Matchers
- def all[K, V, MAP[k, v] <: GenMap[k, v]](xs: MAP[K, V])(implicit collecting: Collecting[(K, V), GenTraversable[(K, V)]], prettifier: Prettifier, pos: Position): ResultOfCollectedAny[(K, V)]
- Definition Classes
- Matchers
- def all[E, C[_]](xs: C[E])(implicit collecting: Collecting[E, C[E]], prettifier: Prettifier, pos: Position): ResultOfCollectedAny[E]
- Definition Classes
- Matchers
- def allElementsOf[R](elements: GenTraversable[R]): ResultOfAllElementsOfApplication
- Definition Classes
- Matchers
- def allOf(firstEle: Any, secondEle: Any, remainingEles: Any*)(implicit pos: Position): ResultOfAllOfApplication
- Definition Classes
- Matchers
- def an[T](implicit arg0: ClassTag[T]): ResultOfAnTypeInvocation[T]
- Definition Classes
- Matchers
- val an: AnWord
- Definition Classes
- Matchers
- final def asInstanceOf[T0]: T0
- Definition Classes
- Any
- macro def assert(condition: Boolean, clue: Any)(implicit prettifier: Prettifier, pos: Position): Assertion
- Definition Classes
- Assertions
- macro def assert(condition: Boolean)(implicit prettifier: Prettifier, pos: Position): Assertion
- Definition Classes
- Assertions
- macro def assertCompiles(code: String)(implicit pos: Position): Assertion
- Definition Classes
- Assertions
- macro def assertDoesNotCompile(code: String)(implicit pos: Position): Assertion
- Definition Classes
- Assertions
- def assertResult(expected: Any)(actual: Any)(implicit prettifier: Prettifier, pos: Position): Assertion
- Definition Classes
- Assertions
- def assertResult(expected: Any, clue: Any)(actual: Any)(implicit prettifier: Prettifier, pos: Position): Assertion
- Definition Classes
- Assertions
- def assertThrows[T <: AnyRef](f: => Any)(implicit classTag: ClassTag[T], pos: Position): Assertion
- Definition Classes
- Assertions
- macro def assertTypeError(code: String)(implicit pos: Position): Assertion
- Definition Classes
- Assertions
- macro def assume(condition: Boolean, clue: Any)(implicit prettifier: Prettifier, pos: Position): Assertion
- Definition Classes
- Assertions
- macro def assume(condition: Boolean)(implicit prettifier: Prettifier, pos: Position): Assertion
- Definition Classes
- Assertions
- def atLeast(num: Int, xs: String)(implicit collecting: Collecting[Char, String], prettifier: Prettifier, pos: Position): ResultOfCollectedAny[Char]
- Definition Classes
- Matchers
- def atLeast[K, V, JMAP[k, v] <: Map[k, v]](num: Int, xs: JMAP[K, V])(implicit collecting: Collecting[Entry[K, V], JMAP[K, V]], prettifier: Prettifier, pos: Position): ResultOfCollectedAny[Entry[K, V]]
- Definition Classes
- Matchers
- def atLeast[K, V, MAP[k, v] <: GenMap[k, v]](num: Int, xs: MAP[K, V])(implicit collecting: Collecting[(K, V), GenTraversable[(K, V)]], prettifier: Prettifier, pos: Position): ResultOfCollectedAny[(K, V)]
- Definition Classes
- Matchers
- def atLeast[E, C[_]](num: Int, xs: C[E])(implicit collecting: Collecting[E, C[E]], prettifier: Prettifier, pos: Position): ResultOfCollectedAny[E]
- Definition Classes
- Matchers
- def atLeastOneElementOf(elements: GenTraversable[Any]): ResultOfAtLeastOneElementOfApplication
- Definition Classes
- Matchers
- def atLeastOneOf(firstEle: Any, secondEle: Any, remainingEles: Any*)(implicit pos: Position): ResultOfAtLeastOneOfApplication
- Definition Classes
- Matchers
- def atMost(num: Int, xs: String)(implicit collecting: Collecting[Char, String], prettifier: Prettifier, pos: Position): ResultOfCollectedAny[Char]
- Definition Classes
- Matchers
- def atMost[K, V, JMAP[k, v] <: Map[k, v]](num: Int, xs: JMAP[K, V])(implicit collecting: Collecting[Entry[K, V], JMAP[K, V]], prettifier: Prettifier, pos: Position): ResultOfCollectedAny[Entry[K, V]]
- Definition Classes
- Matchers
- def atMost[K, V, MAP[k, v] <: GenMap[k, v]](num: Int, xs: MAP[K, V])(implicit collecting: Collecting[(K, V), GenTraversable[(K, V)]], prettifier: Prettifier, pos: Position): ResultOfCollectedAny[(K, V)]
- Definition Classes
- Matchers
- def atMost[E, C[_]](num: Int, xs: C[E])(implicit collecting: Collecting[E, C[E]], prettifier: Prettifier, pos: Position): ResultOfCollectedAny[E]
- Definition Classes
- Matchers
- def atMostOneElementOf[R](elements: GenTraversable[R]): ResultOfAtMostOneElementOfApplication
- Definition Classes
- Matchers
- def atMostOneOf(firstEle: Any, secondEle: Any, remainingEles: Any*)(implicit pos: Position): ResultOfAtMostOneOfApplication
- Definition Classes
- Matchers
- val be: BeWord
- Definition Classes
- MatcherWords
- val behave: BehaveWord
- Attributes
- protected
- Definition Classes
- AnyFlatSpecLike
- val behavior: BehaviorWord
- Attributes
- protected
- Definition Classes
- AnyFlatSpecLike
- def between(from: Int, upTo: Int, xs: String)(implicit collecting: Collecting[Char, String], prettifier: Prettifier, pos: Position): ResultOfCollectedAny[Char]
- Definition Classes
- Matchers
- def between[K, V, JMAP[k, v] <: Map[k, v]](from: Int, upTo: Int, xs: JMAP[K, V])(implicit collecting: Collecting[Entry[K, V], JMAP[K, V]], prettifier: Prettifier, pos: Position): ResultOfCollectedAny[Entry[K, V]]
- Definition Classes
- Matchers
- def between[E, C[_]](from: Int, upTo: Int, xs: C[E])(implicit collecting: Collecting[E, C[E]], prettifier: Prettifier, pos: Position): ResultOfCollectedAny[E]
- Definition Classes
- Matchers
- def cancel(cause: Throwable)(implicit pos: Position): Nothing
- Definition Classes
- Assertions
- def cancel(message: String, cause: Throwable)(implicit pos: Position): Nothing
- Definition Classes
- Assertions
- def cancel(message: String)(implicit pos: Position): Nothing
- Definition Classes
- Assertions
- def cancel()(implicit pos: Position): Nothing
- Definition Classes
- Assertions
- def clone(): AnyRef
- Attributes
- protected[lang]
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.CloneNotSupportedException]) @native()
- val compile: CompileWord
- Definition Classes
- MatcherWords
- val contain: ContainWord
- Definition Classes
- MatcherWords
- def convertEquivalenceToAToBConstraint[A, B](equivalenceOfB: Equivalence[B])(implicit ev: <:<[A, B]): CanEqual[A, B]
- Definition Classes
- TripleEquals → TripleEqualsSupport
- def convertEquivalenceToBToAConstraint[A, B](equivalenceOfA: Equivalence[A])(implicit ev: <:<[B, A]): CanEqual[A, B]
- Definition Classes
- TripleEquals → TripleEqualsSupport
- implicit def convertNumericToPlusOrMinusWrapper[T](pivot: T)(implicit arg0: Numeric[T]): PlusOrMinusWrapper[T]
- Definition Classes
- Tolerance
- implicit def convertSymbolToHavePropertyMatcherGenerator(symbol: Symbol)(implicit prettifier: Prettifier, pos: Position): HavePropertyMatcherGenerator
- Definition Classes
- Matchers
- implicit def convertToAnyShouldWrapper[T](o: T)(implicit pos: Position, prettifier: Prettifier): AnyShouldWrapper[T]
- Definition Classes
- Matchers
- def convertToCheckingEqualizer[T](left: T): CheckingEqualizer[T]
- Definition Classes
- TripleEquals → TripleEqualsSupport
- implicit def convertToEqualizer[T](left: T): Equalizer[T]
- Definition Classes
- TripleEquals → TripleEqualsSupport
- implicit def convertToInAndIgnoreMethods(resultOfStringPassedToVerb: ResultOfStringPassedToVerb): InAndIgnoreMethods
- Attributes
- protected
- Definition Classes
- AnyFlatSpecLike
- implicit def convertToInAndIgnoreMethodsAfterTaggedAs(resultOfTaggedAsInvocation: ResultOfTaggedAsInvocation): InAndIgnoreMethodsAfterTaggedAs
- Attributes
- protected
- Definition Classes
- AnyFlatSpecLike
- implicit def convertToRegexWrapper(o: Regex): RegexWrapper
- Definition Classes
- Matchers
- implicit def convertToStringCanWrapper(o: String)(implicit position: Position): StringCanWrapperForVerb
- Definition Classes
- CanVerb
- implicit def convertToStringMustWrapperForVerb(o: String)(implicit position: Position): StringMustWrapperForVerb
- Definition Classes
- MustVerb
- implicit def convertToStringShouldWrapper(o: String)(implicit pos: Position, prettifier: Prettifier): StringShouldWrapper
- Definition Classes
- Matchers
- implicit def convertToStringShouldWrapperForVerb(o: String)(implicit position: Position): StringShouldWrapperForVerb
- Definition Classes
- ShouldVerb
- val decided: DecidedWord
- Definition Classes
- Explicitly
- def defaultEquality[A]: Equality[A]
- Definition Classes
- TripleEqualsSupport
- val defined: DefinedWord
- Definition Classes
- MatcherWords
- def definedAt[T](right: T): ResultOfDefinedAt[T]
- Definition Classes
- Matchers
- val determined: DeterminedWord
- Definition Classes
- Explicitly
- def dynamicBinding(res0: Boolean, res1: Boolean): Unit
Let’s see how functions create and encapsulate data structures.
Functions and Data
Let’s see how functions create and encapsulate data structures.
We want to design a package for doing rational arithmetic.
A rational number
x / y
is represented by two integers:- its numerator
x
, and - its denominator
y
.
Rational Addition
Suppose we want to implement the addition of two rational numbers.
def addRationalNumerator(n1: Int, d1: Int, n2: Int, d2: Int): Int def addRationalDenominator(n1: Int, d1: Int, n2: Int, d2: Int): Int
It would be difficult to manage all these numerators and denominators!
A better choice is to combine the numerator and denominator of a rational number in a data structure.
Classes
In Scala, we do this by defining a class:
class Rational(x: Int, y: Int) { def numer = x def denom = y }
This definition introduces two entities:
- A new type, named
Rational
. - A constructor
Rational
to create elements of this type.
Scala keeps the names of types and values in different namespaces. So there's no conflict between the two definitions of
Rational
.Objects
We call the elements of a class type objects.
We create an object by prefixing an application of the constructor of the class with the operator
new
.new Rational(1, 2)
Members of an Object
Objects of the class
Rational
have two members,numer
anddenom
.We select the members of an object with the infix operator
.
(like in Java).val x = new Rational(1, 2) // x: Rational = Rational@2abe0e27 x.numer // 1 x.denom // 2
Rational Arithmetic
We can now define the arithmetic functions that implement the standard rules.
n1 / d1 + n2 / d2 = (n1 * d2 + n2 * d1) / (d1 * d2) n1 / d1 - n2 / d2 = (n1 * d2 - n2 * d1) / (d1 * d2) n1 / d1 * n2 / d2 = (n1 * n2) / (d1 * d2) n1 / d1 / n2 / d2 = (n1 * d2) / (d1 * n2) n1 / d1 = n2 / d2 iff n1 * d2 = d1 * n2
Implementing Rational Arithmetic
def addRational(r: Rational, s: Rational): Rational = new Rational( r.numer * s.denom + s.numer * r.denom, r.denom * s.denom ) def makeString(r: Rational) = s"${r.numer}/${r.denom}"
And then:
makeString(addRational(new Rational(1, 2), new Rational(2, 3)))
Methods
One can go further and also package functions operating on a data abstraction in the data abstraction itself.
Such functions are called methods.
Rational numbers now would have, in addition to the functions
numer
anddenom
, the functionsadd
,sub
,mul
,div
,equal
,toString
.Here's a possible implementation:
class Rational(x: Int, y: Int) { def numer = x def denom = y def add(r: Rational) = new Rational(numer * r.denom + r.numer * denom, denom * r.denom) def mul(r: Rational) = ... ... override def toString = s"$numer/$denom" }
Note that the modifier
override
declares thattoString
redefines a method that already exists (in the classjava.lang.Object
).Here is how one might use the new
Rational
abstraction:val x = new Rational(1, 3) val y = new Rational(5, 7) val z = new Rational(3, 2) x.add(y).mul(z)
Data Abstraction
In the above example rational numbers weren't always represented in their simplest form.
One would expect the rational numbers to be simplified:
- reduce them to their smallest numerator and denominator by dividing both with a divisor.
We could implement this in each rational operation, but it would be easy to forget this division in an operation.
A better alternative consists of simplifying the representation in the class when the objects are constructed:
class Rational(x: Int, y: Int) { private def gcd(a: Int, b: Int): Int = if (b == 0) a else gcd(b, a % b) private val g = gcd(x, y) def numer = x / g def denom = y / g ... }
gcd
andg
are private members; we can only access them from inside theRational
class.In this example, we calculate
gcd
immediately, so that its value can be re-used in the calculations ofnumer
anddenom
.It is also possible to call
gcd
in the code ofnumer
anddenom
:class Rational(x: Int, y: Int) { private def gcd(a: Int, b: Int): Int = if (b == 0) a else gcd(b, a % b) def numer = x / gcd(x, y) def denom = y / gcd(x, y) }
This can be advantageous if it is expected that the functions
numer
anddenom
are called infrequently.It is equally possible to turn
numer
anddenom
intoval
s, so that they are computed only once:class Rational(x: Int, y: Int) { private def gcd(a: Int, b: Int): Int = if (b == 0) a else gcd(b, a % b) val numer = x / gcd(x, y) val denom = y / gcd(x, y) }
This can be advantageous if the functions
numer
anddenom
are called often.The Client's View
Clients observe exactly the same behavior in each case.
This ability to choose different implementations of the data without affecting clients is called data abstraction.
It is a cornerstone of software engineering.
Self Reference
On the inside of a class, the name
this
represents the object on which the current method is executed.Add the functions
less
andmax
to the classRational
.class Rational(x: Int, y: Int) { ... def less(that: Rational) = numer * that.denom < that.numer * denom def max(that: Rational) = if (this.less(that)) that else this }
Note that a simple name
x
, which refers to another member of the class, is an abbreviation ofthis.x
. Thus, an equivalent way to formulateless
is as follows.def less(that: Rational) = this.numer * that.denom < that.numer * this.denom
Preconditions
Let's say our
Rational
class requires that the denominator is positive.We can enforce this by calling the
require
function.class Rational(x: Int, y: Int) { require(y > 0, "denominator must be positive") ... }
require
is a predefined function. It takes a condition and an optional message string. If the condition passed torequire
isfalse
, anIllegalArgumentException
is thrown with the given message string.Assertions
Besides
require
, there is alsoassert
.Assert also takes a condition and an optional message string as parameters. E.g.
val x = sqrt(y) assert(x >= 0)
Like
require
, a failingassert
will also throw an exception, but it's a different one:AssertionError
forassert
,IllegalArgumentException
forrequire
.This reflects a difference in intent
require
is used to enforce a precondition on the caller of a function.assert
is used as to check the code of the function itself.
Constructors
In Scala, a class implicitly introduces a constructor. This one is called the primary constructor of the class.
The primary constructor:
- takes the parameters of the class
- and executes all statements in the class body
(such as the
require
a couple of slides back).
Auxiliary Constructors
Scala also allows the declaration of auxiliary constructors.
These are methods named
this
.Adding an auxiliary constructor to the class
Rational
:class Rational(x: Int, y: Int) { def this(x: Int) = this(x, 1) ... }
Classes and Substitutions
We previously defined the meaning of a function application using a computation model based on substitution. Now we extend this model to classes and objects.
How is an instantiation of the class
new C(e1, …, en)
evaluated?The expression arguments
e1, …, en
are evaluated like the arguments of a normal function. That's it.The resulting expression, say,
new C(v1, …, vn)
, is already a value.Now suppose that we have a class definition,
class C(x1, …, xn) { … def f(y1, …, ym) = b … }
where:
- The formal parameters of the class are
x1, …, xn
. - The class defines a method
f
with formal parametersy1, …, ym
.
(The list of function parameters can be absent. For simplicity, we have omitted the parameter types.)
How is the following expression evaluated?
new C(v1, …, vn).f(w1, …, wm)
The following three substitutions happen:
- the substitution of the formal parameters
y1, …, ym
of the functionf
by the argumentsw1, …, wm
, - the substitution of the formal parameters
x1, …, xn
of the classC
by the class argumentsv1, …, vn
, - the substitution of the self reference
this
by the value of the objectnew C(v1, …, vn)
.
Operators
In principle, the rational numbers defined by
Rational
are as natural as integers.But for the user of these abstractions, there is a noticeable difference:
- We write
x + y
, ifx
andy
are integers, but - We write
r.add(s)
ifr
ands
are rational numbers.
In Scala, we can eliminate this difference because operators can be used as identifiers.
Thus, an identifier can be:
- Alphanumeric: starting with a letter, followed by a sequence of letters or numbers
- Symbolic: starting with an operator symbol, followed by other operator symbols.
- The underscore character
'_'
counts as a letter. - Alphanumeric identifiers can also end in an underscore, followed by some operator symbols.
Examples of identifiers:
x1 * +?%& vector_++ counter_=
Operators for Rationals
So, here is a more natural definition of class
Rational
:class Rational(x: Int, y: Int) { private def gcd(a: Int, b: Int): Int = if (b == 0) a else gcd(b, a % b) private val g = gcd(x, y) def numer = x / g def denom = y / g def + (r: Rational) = new Rational( numer * r.denom + r.numer * denom, denom * r.denom ) def - (r: Rational) = ... def * (r: Rational) = ... ... }
and then rational numbers can be used like
Int
orDouble
:val x = new Rational(1, 2) val y = new Rational(1, 3) x * x + y * y
Precedence Rules
The precedence of an operator is determined by its first character.
The following table lists the characters in increasing order of priority precedence:
(all letters) | ^ & < > = ! : + - * / % (all other special characters)
Abstract Classes
Consider the task of writing a class for sets of integers with the following operations.
abstract class IntSet { def incl(x: Int): IntSet def contains(x: Int): Boolean }
IntSet
is an abstract class.Abstract classes can contain members which are missing an implementation (in our case,
incl
andcontains
).Consequently, no instances of an abstract class can be created with the operator
new
.Class Extensions
Let's consider implementing sets as binary trees.
There are two types of possible trees: a tree for the empty set, and a tree consisting of an integer and two sub-trees.
Here are their implementations:
class Empty extends IntSet { def contains(x: Int): Boolean = false def incl(x: Int): IntSet = new NonEmpty(x, new Empty, new Empty) } class NonEmpty(elem: Int, left: IntSet, right: IntSet) extends IntSet { def contains(x: Int): Boolean = if (x < elem) left contains x else if (x > elem) right contains x else true def incl(x: Int): IntSet = if (x < elem) new NonEmpty(elem, left incl x, right) else if (x > elem) new NonEmpty(elem, left, right incl x) else this }
Empty
andNonEmpty
both extend the classIntSet
.This implies that the types
Empty
andNonEmpty
conform to the typeIntSet
- an object of type
Empty
orNonEmpty
can be used wherever an object of typeIntSet
is required.
IntSet
is called the superclass ofEmpty
andNonEmpty
.Empty
andNonEmpty
are subclasses ofIntSet
.In Scala, any user-defined class extends another class.
If no superclass is given, the standard class
Object
in the Java packagejava.lang
is assumed.The direct or indirect superclasses of a class
C
are called base classes ofC
.So, the base classes of
NonEmpty
areIntSet
andObject
.Implementation and Overriding
The definitions of
contains
andincl
in the classesEmpty
andNonEmpty
implement the abstract functions in the base traitIntSet
.It is also possible to redefine an existing, non-abstract definition in a subclass by using
override
.abstract class Base { def foo = 1 def bar: Int } class Sub extends Base { override def foo = 2 def bar = 3 }
Object Definitions
In the
IntSet
example, one could argue that there is really only a single emptyIntSet
.So it seems overkill to have the user create many instances of it.
We can express this case better with an object definition:
object Empty extends IntSet { def contains(x: Int): Boolean = false def incl(x: Int): IntSet = new NonEmpty(x, Empty, Empty) }
This defines a singleton object named
Empty
.No other
Empty
instances can be (or need to be) created.Singleton objects are values, so
Empty
evaluates to itself.Dynamic Binding
Object-oriented languages (including Scala) implement dynamic method dispatch.
This means that the code invoked by a method call depends on the runtime type of the object that contains the method.
- its numerator
- val empty: EmptyWord
- Definition Classes
- MatcherWords
- val endWith: EndWithWord
- Definition Classes
- MatcherWords
- final def eq(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef
- def equal(o: Null): Matcher[AnyRef]
- Definition Classes
- Matchers
- def equal[T](spread: Spread[T]): Matcher[T]
- Definition Classes
- Matchers
- def equal(right: Any): MatcherFactory1[Any, Equality]
- Definition Classes
- MatcherWords
- def equals(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef → Any
- def every(xs: String)(implicit collecting: Collecting[Char, String], prettifier: Prettifier, pos: Position): ResultOfCollectedAny[Char]
- Definition Classes
- Matchers
- def every[K, V, JMAP[k, v] <: Map[k, v]](xs: JMAP[K, V])(implicit collecting: Collecting[Entry[K, V], JMAP[K, V]], prettifier: Prettifier, pos: Position): ResultOfCollectedAny[Entry[K, V]]
- Definition Classes
- Matchers
- def every[K, V, MAP[k, v] <: Map[k, v]](xs: MAP[K, V])(implicit collecting: Collecting[(K, V), GenTraversable[(K, V)]], prettifier: Prettifier, pos: Position): ResultOfCollectedAny[(K, V)]
- Definition Classes
- Matchers
- def every[E, C[_]](xs: C[E])(implicit collecting: Collecting[E, C[E]], prettifier: Prettifier, pos: Position): ResultOfCollectedAny[E]
- Definition Classes
- Matchers
- def exactly(num: Int, xs: String)(implicit collecting: Collecting[Char, String], prettifier: Prettifier, pos: Position): ResultOfCollectedAny[Char]
- Definition Classes
- Matchers
- def exactly[K, V, JMAP[k, v] <: Map[k, v]](num: Int, xs: JMAP[K, V])(implicit collecting: Collecting[Entry[K, V], JMAP[K, V]], prettifier: Prettifier, pos: Position): ResultOfCollectedAny[Entry[K, V]]
- Definition Classes
- Matchers
- def exactly[K, V, MAP[k, v] <: GenMap[k, v]](num: Int, xs: MAP[K, V])(implicit collecting: Collecting[(K, V), GenTraversable[(K, V)]], prettifier: Prettifier, pos: Position): ResultOfCollectedAny[(K, V)]
- Definition Classes
- Matchers
- def exactly[E, C[_]](num: Int, xs: C[E])(implicit collecting: Collecting[E, C[E]], prettifier: Prettifier, pos: Position): ResultOfCollectedAny[E]
- Definition Classes
- Matchers
- final def execute(testName: String, configMap: ConfigMap, color: Boolean, durations: Boolean, shortstacks: Boolean, fullstacks: Boolean, stats: Boolean): Unit
- Definition Classes
- Suite
- val exist: ExistWord
- Definition Classes
- MatcherWords
- def expectedTestCount(filter: Filter): Int
- Definition Classes
- Suite
- def fail(cause: Throwable)(implicit pos: Position): Nothing
- Definition Classes
- Assertions
- def fail(message: String, cause: Throwable)(implicit pos: Position): Nothing
- Definition Classes
- Assertions
- def fail(message: String)(implicit pos: Position): Nothing
- Definition Classes
- Assertions
- def fail()(implicit pos: Position): Nothing
- Definition Classes
- Assertions
- def finalize(): Unit
- Attributes
- protected[lang]
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.Throwable])
- val fullyMatch: FullyMatchWord
- Definition Classes
- MatcherWords
- final def getClass(): Class[_ <: AnyRef]
- Definition Classes
- AnyRef → Any
- Annotations
- @native()
- def hashCode(): Int
- Definition Classes
- AnyRef → Any
- Annotations
- @native()
- val have: HaveWord
- Definition Classes
- MatcherWords
- val ignore: IgnoreWord
- Attributes
- protected
- Definition Classes
- AnyFlatSpecLike
- def inOrder(firstEle: Any, secondEle: Any, remainingEles: Any*)(implicit pos: Position): ResultOfInOrderApplication
- Definition Classes
- Matchers
- def inOrderElementsOf[R](elements: GenTraversable[R]): ResultOfInOrderElementsOfApplication
- Definition Classes
- Matchers
- def inOrderOnly[T](firstEle: Any, secondEle: Any, remainingEles: Any*)(implicit pos: Position): ResultOfInOrderOnlyApplication
- Definition Classes
- Matchers
- val include: IncludeWord
- Definition Classes
- MatcherWords
- def info: Informer
- Attributes
- protected
- Definition Classes
- AnyFlatSpecLike → Informing
- def intercept[T <: AnyRef](f: => Any)(implicit classTag: ClassTag[T], pos: Position): T
- Definition Classes
- Assertions
- final def isInstanceOf[T0]: Boolean
- Definition Classes
- Any
- val it: ItWord
- Attributes
- protected
- Definition Classes
- AnyFlatSpecLike
- val key: KeyWord
- Definition Classes
- Matchers
- val length: LengthWord
- Definition Classes
- MatcherWords
- def lowPriorityTypeCheckedConstraint[A, B](implicit equivalenceOfB: Equivalence[B], ev: <:<[A, B]): CanEqual[A, B]
- Definition Classes
- TripleEquals → TripleEqualsSupport
- def markup: Documenter
- Attributes
- protected
- Definition Classes
- AnyFlatSpecLike → Documenting
- val matchPattern: MatchPatternWord
- Definition Classes
- MatcherWords
- def message(expectedMessage: String): ResultOfMessageWordApplication
- Definition Classes
- Matchers
- final def ne(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef
- def nestedSuites: IndexedSeq[Suite]
- Definition Classes
- Suite
- def no(xs: String)(implicit collecting: Collecting[Char, String], prettifier: Prettifier, pos: Position): ResultOfCollectedAny[Char]
- Definition Classes
- Matchers
- def no[K, V, JMAP[k, v] <: Map[k, v]](xs: JMAP[K, V])(implicit collecting: Collecting[Entry[K, V], JMAP[K, V]], prettifier: Prettifier, pos: Position): ResultOfCollectedAny[Entry[K, V]]
- Definition Classes
- Matchers
- def no[E, C[_]](xs: C[E])(implicit collecting: Collecting[E, C[E]], prettifier: Prettifier, pos: Position): ResultOfCollectedAny[E]
- Definition Classes
- Matchers
- def noElementsOf(elements: GenTraversable[Any]): ResultOfNoElementsOfApplication
- Definition Classes
- Matchers
- def noException(implicit pos: Position): NoExceptionWord
- Definition Classes
- MatcherWords
- def noneOf(firstEle: Any, secondEle: Any, remainingEles: Any*)(implicit pos: Position): ResultOfNoneOfApplication
- Definition Classes
- Matchers
- val not: NotWord
- Definition Classes
- MatcherWords
- def note: Notifier
- Attributes
- protected
- Definition Classes
- AnyFlatSpecLike → Notifying
- final def notify(): Unit
- Definition Classes
- AnyRef
- Annotations
- @native()
- final def notifyAll(): Unit
- Definition Classes
- AnyRef
- Annotations
- @native()
- def of[T](implicit ev: ClassTag[T]): ResultOfOfTypeInvocation[T]
- Definition Classes
- Matchers
- def oneElementOf(elements: GenTraversable[Any]): ResultOfOneElementOfApplication
- Definition Classes
- Matchers
- def oneOf(firstEle: Any, secondEle: Any, remainingEles: Any*)(implicit pos: Position): ResultOfOneOfApplication
- Definition Classes
- Matchers
- def only(xs: Any*)(implicit pos: Position): ResultOfOnlyApplication
- Definition Classes
- Matchers
- def pending: Assertion with PendingStatement
- Definition Classes
- Assertions
- def pendingUntilFixed(f: => Unit)(implicit pos: Position): Assertion with PendingStatement
- Definition Classes
- Assertions
- val readable: ReadableWord
- Definition Classes
- MatcherWords
- def reducer(res0: Int, res1: Int): Unit
Dynamic dispatch of methods is analogous to calls to higher-order functions.
Dynamic dispatch of methods is analogous to calls to higher-order functions.
Can we implement one concept in terms of the other?
- Objects in terms of higher-order functions?
- Higher-order functions in terms of objects?
Traits
In Scala, a class can only have one superclass.
But what if a class has several natural supertypes to which it conforms or from which it wants to inherit code?
Here, you could use
trait
s.A trait is declared like an abstract class, just with
trait
instead ofabstract class
.trait Planar { def height: Int def width: Int def surface = height * width }
Classes, objects and traits can inherit from at most one class but arbitrarily many traits:
class Square extends Shape with Planar with Movable …
On the other hand, traits cannot have (value) parameters, only classes can.
Scala's Class Hierarchy
Top Types
At the top of the type hierarchy we find:
Any
- The base type of all types
- Methods:
==
,!=
,equals
,hashCode
,toString
AnyRef
- The base type of all reference types
- Alias of
java.lang.Object
AnyVal
- The base type of all primitive types
Bottom Type
Nothing
is at the bottom of Scala's type hierarchy. It is a subtype of every other type.There is no value of type
Nothing
.Why is that useful?
- To signal abnormal termination
- As an element type of empty collections
The Null Type
Every reference class type also has
null
as a value.The type of
null
isNull
.Null
is a subtype of every class that inherits fromObject
; it is incompatible with subtypes ofAnyVal
.val x = null // x: Null val y: String = null // y: String val z: Int = null // error: type mismatch
Exercise
The following
Reducer
abstract class defines how to reduce a list of values into a single value by starting with an initial value and combining it with each element of the list: - val regex: RegexWord
- Definition Classes
- Matchers
- final def registerIgnoredTest(testText: String, testTags: Tag*)(testFun: => Any)(implicit pos: Position): Unit
- Definition Classes
- AnyFlatSpecLike → TestRegistration
- final def registerTest(testText: String, testTags: Tag*)(testFun: => Any)(implicit pos: Position): Unit
- Definition Classes
- AnyFlatSpecLike → TestRegistration
- def rerunner: Option[String]
- Definition Classes
- Suite
- def run(testName: Option[String], args: Args): Status
- Definition Classes
- AnyFlatSpecLike → Suite
- def runNestedSuites(args: Args): Status
- Attributes
- protected
- Definition Classes
- Suite
- def runTest(testName: String, args: Args): Status
- Attributes
- protected
- Definition Classes
- AnyFlatSpecLike → TestSuite → Suite
- def runTests(testName: Option[String], args: Args): Status
- Attributes
- protected
- Definition Classes
- AnyFlatSpecLike → Suite
- implicit val shorthandSharedTestRegistrationFunction: StringVerbBehaveLikeInvocation
- Attributes
- protected
- Definition Classes
- AnyFlatSpecLike
- implicit val shorthandTestRegistrationFunction: StringVerbStringInvocation
- Attributes
- protected
- Definition Classes
- AnyFlatSpecLike
- val size: SizeWord
- Definition Classes
- MatcherWords
- val sorted: SortedWord
- Definition Classes
- MatcherWords
- val startWith: StartWithWord
- Definition Classes
- MatcherWords
- final val succeed: Assertion
- Definition Classes
- Assertions
- def suiteId: String
- Definition Classes
- Suite
- def suiteName: String
- Definition Classes
- Suite
- final def synchronized[T0](arg0: => T0): T0
- Definition Classes
- AnyRef
- def tags: Map[String, Set[String]]
- Definition Classes
- AnyFlatSpecLike → Suite
- def testDataFor(testName: String, theConfigMap: ConfigMap): TestData
- Definition Classes
- AnyFlatSpecLike → Suite
- def testNames: Set[String]
- Definition Classes
- AnyFlatSpecLike → Suite
- def the[T](implicit arg0: ClassTag[T], pos: Position): ResultOfTheTypeInvocation[T]
- Definition Classes
- Matchers
- def theSameElementsAs(xs: GenTraversable[_]): ResultOfTheSameElementsAsApplication
- Definition Classes
- Matchers
- def theSameElementsInOrderAs(xs: GenTraversable[_]): ResultOfTheSameElementsInOrderAsApplication
- Definition Classes
- Matchers
- val theSameInstanceAs: TheSameInstanceAsPhrase
- Definition Classes
- Matchers
- val they: TheyWord
- Attributes
- protected
- Definition Classes
- AnyFlatSpecLike
- def thrownBy(fun: => Any): ResultOfThrownByApplication
- Definition Classes
- Matchers
- def toString(): String
- Definition Classes
- AnyFlatSpec → AnyRef → Any
- val typeCheck: TypeCheckWord
- Definition Classes
- MatcherWords
- def typeCheckedConstraint[A, B](implicit equivalenceOfA: Equivalence[A], ev: <:<[B, A]): CanEqual[A, B]
- Definition Classes
- TripleEquals → TripleEqualsSupport
- implicit def unconstrainedEquality[A, B](implicit equalityOfA: Equality[A]): CanEqual[A, B]
- Definition Classes
- TripleEquals → TripleEqualsSupport
- val value: ValueWord
- Definition Classes
- Matchers
- final def wait(): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.InterruptedException])
- final def wait(arg0: Long, arg1: Int): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.InterruptedException])
- final def wait(arg0: Long): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.InterruptedException]) @native()
- def withClue[T](clue: Any)(fun: => T): T
- Definition Classes
- Assertions
- def withFixture(test: NoArgTest): Outcome
- Attributes
- protected
- Definition Classes
- TestSuite
- val writable: WritableWord
- Definition Classes
- MatcherWords
Deprecated Value Members
- def conversionCheckedConstraint[A, B](implicit equivalenceOfA: Equivalence[A], cnv: (B) => A): CanEqual[A, B]
- Definition Classes
- TripleEquals → TripleEqualsSupport
- Annotations
- @deprecated
- Deprecated
(Since version 3.1.0) The conversionCheckedConstraint method has been deprecated and will be removed in a future version of ScalaTest. It is no longer needed now that the deprecation period of ConversionCheckedTripleEquals has expired. It will not be replaced.
- def convertEquivalenceToAToBConversionConstraint[A, B](equivalenceOfB: Equivalence[B])(implicit ev: (A) => B): CanEqual[A, B]
- Definition Classes
- TripleEquals → TripleEqualsSupport
- Annotations
- @deprecated
- Deprecated
(Since version 3.1.0) The convertEquivalenceToAToBConversionConstraint method has been deprecated and will be removed in a future version of ScalaTest. It is no longer needed now that the deprecation period of ConversionCheckedTripleEquals has expired. It will not be replaced.
- def convertEquivalenceToBToAConversionConstraint[A, B](equivalenceOfA: Equivalence[A])(implicit ev: (B) => A): CanEqual[A, B]
- Definition Classes
- TripleEquals → TripleEqualsSupport
- Annotations
- @deprecated
- Deprecated
(Since version 3.1.0) The convertEquivalenceToBToAConversionConstraint method has been deprecated and will be removed in a future version of ScalaTest. It is no longer needed now that the deprecation period of ConversionCheckedTripleEquals has expired. It will not be replaced.
- def lowPriorityConversionCheckedConstraint[A, B](implicit equivalenceOfB: Equivalence[B], cnv: (A) => B): CanEqual[A, B]
- Definition Classes
- TripleEquals → TripleEqualsSupport
- Annotations
- @deprecated
- Deprecated
(Since version 3.1.0) The lowPriorityConversionCheckedConstraint method has been deprecated and will be removed in a future version of ScalaTest. It is no longer needed now that the deprecation period of ConversionCheckedTripleEquals has expired. It will not be replaced.
- final val styleName: String
- Definition Classes
- AnyFlatSpecLike → Suite
- Annotations
- @deprecated
- Deprecated
(Since version 3.1.0) The styleName lifecycle method has been deprecated and will be removed in a future version of ScalaTest with no replacement.