
Copyright © Cay S. Horstmann 2015
class Point(val x: Double, val y: Double) {
def move(dx: Double, dy: Double) = new Point(x + dx, y + dy)
def distanceFromOrigin = math.sqrt(x * x + y * y)
override def toString = f"(${x}, ${y})"
}
move, distanceFromOrigin, toStringoverride when overriding methods (here Object.toString)() for parameterless accessor methodsx, y with getters, call p.x, p.yf"Hello, ${name}!" fills the value of the expression name into the string.
printf-style formatters: f"${x}%8.2f"Point is an immutable class—can't change the val fields:
p.x, p.y can only be used to read, not to mutate, the instance fields move yields a new object!var for mutable instance variables:
class Point(var x: Double, var y: Double)
p.x, p.y.var or val:
class BankAccount {
private var balance = 0.0
...
}
class Point(val x: Double, val y: Double) {
def this() { this(0, 0) }
...
}
new Point(3, 4)new Point()class Point(val x: Double = 0, val y: Double = 0)
class Point(val x: Double, val y: Double) {
println(f"Welcome to (${x}, ${y})")
// Printed whenever a new point is constructed
...
}
p.x, you don't know whether x is a field or a method.x could have been defined as a field:
class Point(val x: Double, ...)
x could have been a method:
class Point(...) {
private val r = ...
private val theta = ...
def x = r * cos(theta)
...
}
x op y is the same as x.op(y).1 to 10 map (3 * _) filter (_ % 5 == 2)
class Point(...) {
...
def *(factor: Double) = new Point(x * factor, y * factor)
}
p.*(2) or p * 2, whichever you prefer.:, it is right-associative. 1 :: 2 :: 3 :: NilThe parentheses group to the right:
1 :: (2 :: (3 :: Nil))
apply method: map(key) is map.apply(key).object for singletons, static methods:
object Accounts {
private var lastNumber = 0
def newUniqueNumber() = { lastNumber += 1; lastNumber }
// Aside: Use () since it mutates state
}
App is like main:
object MyApp extends App {
println(f"Hello, ${args(0)}!")
}
class Point { ... }
object Point { ... }
apply in companion object for factory methods:
object Point {
def apply(x: Double, y: Double) = new Point(x, y)
}
new:
val p = Point(3, 4) * factor // prettier than new Point(3, 4)

Time with read-only fields hours and minutes, a method toString, and a method before(other: Time): Boolean that checks whether this time comes before the other. A Time object should be constructed as new Time(h, m), where h is between 0 and 23 and m between 0 and 59. If they aren't, call throw new IllegalArgumentException.Time objects and test your before method.new Time(hrs). There are two different ways. What are they?In a new worksheet, reimplement the Time class from the preceding exercise so that the internal representation is the number of minutes since midnight (between 0 and 24 × 60 – 1). Do not change the public interface.
Do not use var or val in the primary constructor!
class Time(h: Int, m: Int) {
private val minutesSinceMidnight = ...
...
}
Supply parameterless methods hours, minutes.
minutes into a mutable field, so that the following is okay:
val start = new Time(13, 0) start.minutes = 15What did you have to do?
_=, like this:
def minutes_=(newValue: Int) { ... }
start.minutes = -100How can you avoid that in the modified implementation?
Time class have to make when switching from the original to the reimplemented class?Do the following with either the original or the reimplemented Time class (your choice):
before method of part 1 so that one can call:
if (t1 < t2) ...
- that, given a Time object, yields the number of minutes between them (between -1439 and 1439).Time object can be constructed without calling new.