222
CHAPTER 7
■ TRAITS AND TYPES AND GNARLY STUFF FOR ARCHITECTS
Is the creature dead? Scala allows you to have symbols as well as letters and numbers in
method names, but in order to mix symbols and letters and numbers, you have to separate
the symbols with the underscore.
def dead_? = life == 0
An instance of Weapon defines a turn or a whole battle tilDeath between Us and Them. The
Weapon takes a function, turn, that transforms instances of Us and Them based on particular
rules. For example, our
Rabbit has three bombs that he can throw. Each time the Rabbit
throws a bomb, we have to update the
Rabbit to have fewer bombs. This is the transformation
rule for the bomb. We define the transformation rule, and the
Weapon instance applies the
transformation rule to an instance of our enemy,
Them, once or until one of the participants
is dead.
protected case class Weapon(turn: (Us, Them) => (Us, Them)) {
Normally, battles are single turns. This gives you the ability to repeat the battle until
one of the participants is dead. There’s an alternate constructor that modifies the
_tilDeath flag.
private var _tilDeath = false
private def this(f: (Us, Them) => (Us, Them), s: Boolean) = {
this(f)
_tilDeath = s
}
If we want to battle tilDeath, we call this method, which will return a new Weapon
instance with the
_tilDeath flag set.
def tilDeath = new Weapon(turn, true)
The apply method is the heart of the class. The public apply method takes a Them param-
eter and calls the private
apply method with the instance of the Creature that created the
Weapon and Them. The private method (callable from anything in the Creature scope) takes
instances of
Us and Them and pits them together in doBattle. If either of the participants
dies, it prints a message. Finally, it returns a
(Us, Them) with Rebattle, which is the (Us,
Them) Tuple contains a Rebattle trait. Rebattle allows you to chain (apply) another Weapon
instance type safely such that the result is another
(Us, Them) with Rebattle. This means
our
Rabbit can throw a bomb in the first turn and then use a sword in the next. However,
our
Rabbit cannot use the Dragon’s tail as a weapon.
def apply(t: Them): (Us, Them) with Rebattle = apply(Creature.this, t)
private[Creature] def apply(seed: Us, t: Them) = {
val ret = doBattle(seed, t)
ret match {
19897ch07.fm Page 222 Monday, April 20, 2009 4:36 PM