
Copyright © Cay S. Horstmann 2015
val now = new java.util.Date // and not java.sql.Date
package com {
package horstmann {
package impatient {
class Employee
...
}
}
}Fully qualified name: com.horstmann.impatient.Employeepackage com.horstmann.impatientLike in Java: The entire source file is in this package.
import java.util.Date val now = new Date // shortcut for new java.util.Date
import java.util._ import java.lang.Math._ // like import static in Java
import java.awt.{Color, Font} // import two classes
import java.util.{HashMap => JavaHashMap} // alias
import java.util.{HashMap => _, _} // hide a class
class Manager {
import scala.collection.mutable._
val subordinates = new ArrayBuffer[Employee]
...
}java.lang, scala, Predef are always imported.java.util and java.util.regex.package com {
package horstmann {
object App {
def run { ... }
}
package impatient {
new App(...)
}
}
}App could be com.horstmann.App or scala.App._root_.scala.App to disambiguate.class Manager extends Employee
e.isInstanceOf[Manager] // like e instanceof Manager e.asInstanceOf[Manager] // like (Manager) e e.getClass == classOf[Manager] // like Manager.class
class Employee(name: String, age: Int, val salary: Double) extends Person(name, age)
class Employee extends Person with Cloneable with Serializable

class ArrayBuffer[A] extends AbstractBuffer[A] with Buffer[A] with GenericTraversableTemplate[A, ArrayBuffer] with BufferLike[A, ArrayBuffer[A]] with IndexedSeqOptimized[A, ArrayBuffer[A]] with Builder[A, ArrayBuffer[A]] with ResizableArray[A] with CustomParallelizable[A, ParArray[A]] with Serializable
trait Logged {
def log(msg: String) {}
}
trait ConsoleLogger extends Logged {
override def log(msg: String) { println(msg) }
}
class SavingsAccount extends Logged {
private var balance: Double = 0
def withdraw(amount: Double) {
if (amount > balance) log("Insufficient funds")
else balance -= amount
}
// ...
}
val acct = new SavingsAccount with ConsoleLogger
val acct2 = new SavingsAccount with FileLogger
trait TimestampLogger extends Logged {
override def log(msg: String) {
super.log(new java.util.Date() + " " + msg)
}
}
trait ShortLogger extends Logged {
val maxLength = 15
override def log(msg: String) {
super.log(
if (msg.length <= maxLength) msg
else msg.substring(0, maxLength - 3) + "...")
}
}
val acct1 = new SavingsAccount with ConsoleLogger
with TimestampLogger with ShortLogger
acct1.withdraw(1000) // Sun Nov 01 17:45:45 ICT 2015 Insufficient...


java.awt.Rectangle class has a method translate that moves a rectangle by a given amount. Try it out: In a worksheet, import the java.awt package, construct a new Rectangle(5, 10, 20, 30), call translate(10, 20), and see what its coordinates are now.java.awt.geom.Ellipse2D.Double. Make an instance val egg = new geom.Ellipse2D.Double(5, 10, 20, 30). Why didn't you have to put java.awt before geom?egg.translate(10, 20). What happens?Ellipse2D, or better, its superclass RectangularShape? We can fix that in Scala. Define a trait:
trait RectangleLike {
def setFrame(x: Double, y: Double, w: Double, h: Double): Unit
def getX: Double
def getY: Double
def getWidth: Double
def getHeight: Double
def translate(dx: Double, dy: Double) { setFrame(getX + dx, getY + dy, getWidth, getHeight) }
}
Now change the definition of egg so that the call to translate works. What did you do?val acct2 = new SavingsAccount
with ConsoleLogger with ShortLogger with TimestampLogger {
override val maxLength = 20
}
Without running the program, what do you think will happen when you call acct2.withdraw(1000)?val acct3 = new SavingsAccount with ShortLogger with TimestampLogger with ConsoleLogger
java.io library, one has to work hard to get services such as buffering:
new BufferedReader(new InputStreamReader(new FileInputStream("/usr/share/dict/words"))) It shouldn't be so hard to add buffering. (Buffering means not to read each byte separately but to read them a chunk at a time.) Here is a Scala trait:
trait Buffered extends InputStream {
val SIZE = 1024
private var end = 0
private val buffer = new Array[Byte](SIZE)
private var pos = 0
override def read() = {
if (pos == end) {
end = super.read(buffer, 0, SIZE)
pos = 0
}
if (pos == end) -1 else {
pos += 1
buffer(pos - 1)
}
}
}
Mix in Buffered into a new FileInputStream("/usr/share/dict/words") (or some other file if you aren't running Linux/Mac OS). How do you do that? Then call read a few times. What do you get?