Chapter 7, Exercise 1, Thinking in Scala
Exercise 1 asks: Add a new method in the base class of Shapes.java that prints a message, but dont override it in the derived classes. Explain what happens. Now override it in one of the derived classes but not the others, and see what happens. Finally, override it in all the derived classes.
Ok, I translated Shapes.java into scala. I added the extra method.
First explanation: Ummm, nothing happens differently at all if you
don't also call the new method. So I did. Explanations:
Omit the derived class roll methods, and they all
roll using the Shape.roll. Omit only the Triangle.roll
override (they don't roll so good anyway) and the Triangles end up
rolling using the Shape.roll, while the others roll in their own
peculiar ways.
// c7xShapes.scala ... Java-style Polymorphism in scala.
package x;
trait Shape {
def draw : unit = ();
def erase : unit = ();
def roll : unit = W.rn( "Shape.roll" );
}
class Circle with Shape {
override def draw : unit = W.rn( "Circle.draw" );
override def erase : unit = W.rn( "Circle.erase");
override def roll : unit = W.rn( "Circle.roll smoothly");
}
class Square with Shape {
override def draw : unit = W.rn( "Square.draw" );
override def erase : unit = W.rn( "Square.erase");
override def roll : unit = W.rn( "Square.roll klunk klunk klunk klunk");
}
class Triangle with Shape {
override def draw : unit = W.rn( "Triangle.draw" );
override def erase : unit = W.rn( "Triangle.erase");
override def roll : unit = W.rn( "Triangle.roll klank klank klank");
}
// A "factory" that randomly creates shapes:
class RandomShapeGenerator {
private var rand = new java.util.Random();
def next : Shape = {
rand.nextInt(3) match {
case 0 => new Circle;
case 1 => new Square;;
case 2 => new Triangle;
}
}
}
object Shapes {
private var gen = new RandomShapeGenerator;
def main ( args: Array[String] ) = {
var s = new Array[Shape]( 9 );
for( val i <- Iterator.range(0, s.length) )
s(i) = gen.next;
for( val i <- Iterator.range(0, s.length) )
s(i).draw;
for( val i <- Iterator.range(0, s.length) )
s(i).roll;
/* One of these days, I ought to write a Scala
equivalent of Bruce's Test/monitor classes. */
}
}
Oh, yeah, I guess I never really made it explicit that I use a small abbreviation for all of these expository printout messages. Here's W.scala:
package x;
object W {
def r ( s: String ) = Console.print( s );
def rn ( s: String ) = Console.println( s );
}
10:19:00 PM