The Lay of The Land: Chapter Objectives
The Lay of The Land: Chapter Objectives
F
Appendix F can be used to either look ahead to what you will be
learning, or as a review for what you have learned. This appendix
provides a view of the lay of the land. It’s like standing on a high
hill at the beginning of a hike to see what kind of interesting
places lie ahead – or surveying the view at the end of the hike to
see where you’ve been.
If you are at the beginning of your hike and looking ahead,
this chapter gives a glimpse of nine interesting places in the jour
ney to becoming an object-oriented programmer. By getting an
early view of them, you will know a little bit of what is to come,
and be better able to integrate what you are learning into a cohe
sive whole. And, as any hiker knows, trudging up a mountain is
easier if you can look forward to what lies at the top and on the
other side. Obviously, there will be lots of details clarified later.
If you are at the end of your hike and looking backwards, this
appendix can help you remember where all you’ve been and what
you’ve learned. It could be used, for example, as part of your
review before an exam.
Chapter Objectives
¾ To see how to extend classes with new services.
¾ To see how to perform a task repeatedly.
¾ To see how programs can decide whether to take an action.
¾ To see how to remember information temporarily.
¾ To see how to make services more flexible by receiving information
when they are executed.
¾ To see how to interact with the program’s user.
¾ To see how to remember information for an object’s lifetime.
¾ To see how to send the same message to different kinds of objects,
with each object behaving in a way appropriate for itself.
¾ To see how to gather similar information together with a collection.
468 Appendix F: The Lay of the Land
Listing F-1: Much of the program to collect flashers from the construction site.
1 import becker.robots.*; Find The Code:
2 layofland/extend
4 {
15
29
34
37
30 karel.pickThing();
40 karel.move();
41 karel.pickThing();
42 karel.move();
43 karel.pickThing();
44 karel.move();
45 karel.pickThing();
46 karel.turnLeft();
47 karel.turnLeft();
48
49 jasmine.pickThing();
50 jasmine.move();
68 }
69 }
karel.turnAround();
karel, jasmine and pat have all the capabilities of ordinary robots.
They can move, turn left, pick things up, and put things down. They can also
collect a row of four flashers and turn around, thanks to the definitions con
tained in Listing F-2. And so, we can replace lines 39 to 47 in Listing F-1
with just two lines:
F.1 Extending an Existing Class 471
karel.collectFlashers();
karel.turnAround();
4 {
7 }
that we learned in Chapter 1. Use the same name both places that
«className» appears.
Listing F-3: A template for creating a new kind of robot with a new service. Additional ser
vices may also be added.
1 import becker.robots.*;
4 {
5 public «className»(City city, int ave, int str, int dir)
6 { super(city, ave, str, dir);
7 }
8
9 «newService»
10 }
In fact, this same technique can also be used to create a new kind of city
that has new services to place walls and flashers for the construction site.
The new kind of city might be called a ConSite, short for “construction site.”
It has two new services, one for placing barriers (walls) and another for plac
ing flashers.
Using a ConSite city and Collector robots significantly shortens our
main program, making it easier to read and understand. The revised program
is shown in Listing F-4. This program behaves exactly the same as the 69 line
program shown in Listing F-1, but is much simpler and easier to read.
Listing F-4: A new version of the program using a new kind of robot and a new kind of city.
layofland/extend 2
4 {
5 public static void main(String[] args)
6 { ConSite site = new ConSite();
7 site.placeBarriers();
8 site.placeFlashers();
9
10 Collector karel =
11 new Collector(site, 1, 1, Directions.EAST);
12 Collector jasmine =
13 new Collector(site, 1, 2, Directions.EAST);
14 Collector pat =
15 new Collector(site, 1, 3, Directions.EAST);
16
17 CityFrame frame = new CityFrame(site, 6, 5);
18
continued…
F.2 Repeating Statements 473
If we can define the Collector robots this way, then karel, jasmine, and
pat can all be the same kind of robot.
Many tasks do the same Java’s while statement can be used to repeat statements over and over.
steps over and over, until
the task is finished. The while statement can be used whenever a task is composed of identical
steps that are repeated until the task is done. In this case, the identical steps
are collecting a flasher and moving to the next intersection. These steps are
repeated until the opposite wall is reached. Using this algorithm, each of the
three robots will perform correctly even though they are collecting flashers on
different lengths of street.
A version of collectFlashers that uses this idea is shown in Listing F
5. The while statement extends from line 11 to line 14 and consists of three
parts.
¾ The keyword while signals to Java that something is going to be re
peated.
¾ The condition determines if the statements should be repeated again.
In this example, the condition is (this.frontIsClear()) – is this
robot’s front clear of anything that can prevent it from moving (like a
wall)?
¾ The body of the while statement, the part between { and }, is the
code that is repeated.
Listing F-5: The Collector class, defined with a while loop in collectFlashers.
layofland/repetition 2
4 {
7 }
11 { while (this.frontIsClear())
12 { this.pickThing();
13 this.move();
14 }
15 this.pickThing();
16 }
17
20 { this.turnLeft();
21 this.turnLeft();
22 }
23 }
How does this while loop work? When a robot is told to collect-
Flashers, the while loop first checks if the robot’s front is clear. That is, it
checks if it is blocked from moving forwards. If its front is clear, then it does
everything in the braces at lines 12-14. After it picks up a flasher and moves
to the next intersection, execution returns to line 11. The robot again checks
if its front is clear. If it is, everything in the braces is executed. This keeps
happening – check if the front is clear, and if it is, do everything in the braces
– until the front is not clear. Then execution resumes at line 15 – the line fol
lowing the while loop’s closing brace. Figure F-4 illustrates this process.
Figure F-4: Illustrating the execution of a while loop. The dark lines in the code indicate the statements that are executed
to arrive at the situation shown on the right.
while (this.frontIsClear())
{ this.pickThing();
this.move();
}
this.pickThing();
while (this.frontIsClear())
{ this.pickThing();
this.move();
}
this.pickThing();
while (this.frontIsClear())
{ this.pickThing();
this.move();
}
this.pickThing();
while (this.frontIsClear())
{ this.pickThing();
this.move();
}
this.pickThing();
The while loop contains one pickThing instruction and one move in
struction, so the robot will always pick something up just as often as it moves.
However, the initial situation shows that it needs to move twice but pick up
476 Appendix F: The Lay of the Land
three flashers. Thus, there must be one pickThing instruction after the loop
to ensure that the extra flasher is picked up.
Use a while loop to exe A while loop is useful to repeat some code over and over. In this exam
cute the same code an
unknown number of times.
ple, the repeated code picked something up and moved. A robot could also
use a while loop to move until a streetlight is encountered, to pick up all the
flashers on a corner, to turn left until its front is clear, and so on.
if (karel.isBesideThing())
{ karel.pickThing();
if (karel.besideThing())
if (karel.besideThing())
{ karel.pickThing();
{ karel.pickThing();
}
}
karel.move();
karel.move();
Now, we need to apply this knowledge to keep karel, jasmine, and pat
from malfunctioning when they do their jobs. The code we need to fix is the
collectFlashers service in Listing F-5. Each use of this.pickThing()
must be replaced with three lines:
478 Appendix F: The Lay of the Land
if (this.isBesideThing())
{ this.pickThing();
{ this.pickThing(Predicate.aFlasher);
this.pickFlasherIfPresent();
4 {
7 }
11 { while (this.frontIsClear())
12 { this.pickFlasherIfPresent();
13 this.move();
14 }
15 this.pickFlasherIfPresent();
16 }
17
20 { if (this.isBesideThing(Predicate.aFlasher))
21 { this.pickThing(Predicate.aFlasher);
22 }
23 }
24
This presents a problem. karel, jasmine, and pat had been using the
walls to determine when to stop collecting flashers. Without the walls, they
will keep going east. At each intersection they will check for a flasher. Not
finding one, they will go to the next intersection and check again – forever.
One possible solution is for each robot to count the number of moves it
makes. Each robot should move four times, attempting to collect a flasher
before each move. Then, collect the last flasher (if there is one) and turn
around. A significant disadvantage of this plan is that karel and pat will
have to travel farther than before. We will simply accept that limitation for
now.
Variables store or remem To make this plan work, each robot will need to remember how many
ber information.
moves it has made while it is collecting the flashers. Java provides variables to
store or remember information. A variable is like a box with a name. Each
variable stores a piece of information; in this case, a number. The number
can be replaced by a new number at any time.
The following code creates a new variable named numMoves and stores a
number, zero, in it.
int numMoves = 0;
A different number, in this case five, can be stored in numMoves like this:
numMoves = 5;
Notice that “int” is only used the first time, when the variable was created.
“int” indicates that the variable will store an integer, a certain kind of num
ber.
F.4 Temporary Memory 481
a = numMoves + 1;
will first create a new variable named “a”. In the next line, Java will first get
the number stored in numMoves (5) and add 1 to it, obtaining 6. This new
number is then put into the variable a, replacing the number that was there.
The variable on the left side of the equals sign is forced to have the value cal
culated on the right side of the equals sign.
We can also use the same variable on both the left and the right side of
the equals sign. For example,
numMoves = numMoves + 1;
gets the current number stored in numMoves (5) and adds 1 to it. This new Variables can be used to
count.
number, 6, is then stored in the variable named on the left side of the equals
sign. That is, numMoves is now one larger than it used to be. This is the fun
damental step in counting – remembering a number one larger than the pre
vious number.
Now, we can combine counting with a while loop to move a robot four
times, a slight simplification of collecting flashers.
public void move4()
{ int numMoves = 0;
{ this.move();
numMoves = numMoves + 1;
To solve the flasher collection problem for karel, jasmine, and pat, the
code shown in Figure F-9 must also pick up a flasher just before the robot
moves, if one is present and again after the loop exits. This change is shown
in Listing F-7. This version of collectFlashers always moves four times
and checks five intersections for flashers. To understand why, look again at
Figure F-9 – the robot moves four times but visits five intersections.
Figure F-9: Illustrating the execution of a counted while loop.
int numMoves = 0;
numMoves
while (numMoves < 4) is 0
{ this.move();
numMoves = numMoves + 1;
}
int numMoves = 0;
numMoves
while (numMoves < 4) is 1
{ this.move();
numMoves = numMoves + 1;
}
int numMoves = 0;
numMovesnumMovesnumMoves
while (numMoves < 4) is 2 is 3 is 4
{ this.move();
numMoves = numMoves + 1;
}
int numMoves = 0;
numMoves
while (numMoves < 4) is 4
{ this.move();
numMoves = numMoves + 1;
}
F.4 Temporary Memory 483
Listing F-7: A version of collectFlashers that always checks exactly five intersections.
1 public void collectFlashers()
2 { int numMoves = 0;
2 { int numThingsFound = 0;
3 while (this.isBesideThing())
4 { this.pickThing();
5 numThingsFound = numThingsFound + 1;
6 }
7
8 int numPutBack = 0;
9 while (numPutBack < numThingsFound/2)
10 { this.putThing();
11 numPutBack = numPutBack + 1;
12 }
13 }
The first loop, at lines 3-6, is not a counted loop. We don’t know how
many times it will execute. Rather, it repeats while there is still something on
the intersection, counting the number of things it picks up. This count is
kept in a temporary variable named numThingsFound.
The second loop, at lines 9-12, is a counted loop. It divides the number
of things found by 2 to calculate how many times to execute. As long as
numPutBack is less than this number, another thing is put down and the
count of things put down is incremented by one.
Temporary variables have Remembering information temporarily in a variable is useful beyond con
uses beyond controlling
loops. trolling loops. In the last example, the robot remembered how many things
were on the intersection so it could put back half of them. It might remem
ber which avenue and street it was on before beginning a task so it can return
there when it’s done, or the direction it’s facing so it can turn that way again.
tell each robot how many intersections to check. This would be done in the
main method. In Listing F-4 we wrote
16 karel.collectFlashers();
17 karel.turnAround();
18
19 jasmine.collectFlashers();
20 jasmine.turnAround();
21
22 pat.collectFlashers();
23 pat.turnAround();
We would like to replace these lines with statements that specify the number
of intersections the robot should check. For example,
16 karel.collectFlashers(4);
17 karel.turnAround();
18
19 jasmine.collectFlashers(5);
20 jasmine.turnAround();
21
22 pat.collectFlashers(3);
23 pat.turnAround();
With this change, the main method tells karel to check four intersec
tions. Similarly, jasmine and pat are told to check five and three intersec
tions, respectively.
Implementing this ability requires communicating the 3, 4 or 5 (or any Parameters are used to
give additional information
other number) from the place where collectFlashers is called to the place required to complete a job.
where the number is used – the definition of collectFlashers. Adding a
parameter to collectFlashers facilitates this communication.
We need to make some minor modifications to the definition of
collectFlashers to receive the parameter given in main. The new version
is shown in Listing F-9. The changes from the previous version, described on
page 485, are in bold.
Listing F-9: A more flexible version of collectFlashers that uses a parameter.
1 public void collectFlashers(int numIntersections)
2 { int numMoves = 0;
5 { this.pickFlasherIfPresent();
6 this.move();
7 numMoves = numMoves + 1;
8 }
9 this.pickFlasherIfPresent();
10 }
6 site.placeFlashers();
8 Collector karel =
10 Collector jasmine =
12 Collector pat =
14
16
17 karel.collectFlashers(4);
18 karel.turnAround();
19
20 jasmine.collectFlashers(5);
21 jasmine.turnAround();
22
23 pat.collectFlashers(3);
24 pat.turnAround();
25 }
26 }
Listing F-11: A new kind of city with a service to place flashers on the construction site.
1 import becker.robots.*; Find The Code:
2 layofland/parameters
3 public class ConSite extends City
4 { public ConSite()
5 { super();
6 }
16 }
17 }
Listing F-12: A new kind of robot that can collect flashers from a specified number of
intersections.
layofland/parameters 2
4 {
7 }
10 { int numMoves = 0;
13 { this.pickFlasherIfPresent();
14 this.move();
15 numMoves = numMoves + 1;
16 }
17 this.pickFlasherIfPresent();
18 }
19
22 { if (this.isBesideThing(Predicate.aFlasher))
23 { this.pickThing(Predicate.aFlasher);
24 }
25 }
26
28 { this.turnLeft();
29 this.turnLeft();
30 }
31 }
We will repeat these three steps three times, once for each robot. After we
have all the information stored in the temporary variables, we can use the
variables to tell each of the robots how many intersections to visit.
When the program actually runs, the user will be asked for the informa
tion in a separate window, called the console, shown in Figure . The user will
likely need to click on the console to bring it to the front before it will accept
input from the keyboard. After each number is typed, the user should press
the “Enter” key. If something other than a number without a decimal point
is typed, the program will give an error message and stop.
Figure F-10: Asking the user for information.
Consider the situation shown in Figure F-10 and suppose the user enters
3 for the last number. When the “Start” button is clicked, the top-most robot
will collect flashers from 40 intersections, proceeding off the right edge of the
display in the process. The middle robot will collect the flasher from (1,2),
proceed to (2,2), and turn around. The bottom robot will collect the flashers
from three intersections, and then turn around.
490 Appendix F: The Lay of the Land
So what does the code to do this look like? For each of the three steps
listed earlier we would write instructions like this:
System.out.print("Number of intersections karel should check: ");
in.readLine();
The first line uses a special object, System.out, to print a message on the
console window. The object’s print service simply prints the characters that
appear between the double quotes in its parameter.
The second line does two things. First, it creates a new temporary vari
able, kNum, the number of intersections karel should check for flashers.
Then it uses an object named in to get a number from the user, putting the
number it gets into kNum. In Figure F-10 the user has entered the number 40;
the readInt service gets this number and places it in kNum.
In the third line, the readLine service is used to process the rest of the
line where the user entered the number 40, preparing for the next cycle of
asking for information and getting it.
Key Idea: System.out is These three lines of code use two objects, System.out and in.
used to show the user tex System.out is a special object that is automatically constructed when the
tual information.
Key Idea: Create an in
program starts. It’s primary service is print. The other object, in, must be
stance of TextInput to constructed by the programmer before it is used. Its construction is similar to
obtain textual information the construction of Robot or City objects except that the name of the class is
from the user. TextInput:
This directs karel to check 40 intersections for flashers, assuming the inter
action shown in Figure F-10.
Listing F-13 shows how to integrate this new code into the main method.
F.6 Asking the User 491
Listing F-13: A program which asks the user how many intersections each robot should
check.
1 import becker.robots.*;
2 import becker.io.*;
6 {
// This part is the same as lines 6-13 of Listing F-10
16
17 TextInput in = new TextInput();
18
19 System.out.print("Number of intersections karel should check: ");
20 int kNum = in.readInt();
21 in.readLine();
22
23 System.out.print("Number of intersections jasmine should check: ");
24 int jNum = in.readInt();
25 in.readLine();
26
27 System.out.print("Number of intersections pat should check: ");
28 int pNum = in.readInt();
29 in.readLine();
30
31 karel.collectFlashers(kNum);
32 karel.turnAround();
33
34 jasmine.collectFlashers(jNum);
35 jasmine.turnAround();
36
37 pat.collectFlashers(pNum);
38 pat.turnAround();
39 }
40 }
jasmine.collectFlashers(jNum);
jasmine.turnLeft();
jasmine.move();
jasmine.turnLeft();
jasmine.collectFlashers(jNum);
jasmine.turnAround();
System.out.println(jasmine.numFlashersCollected());
pat.collectFlashers(pNum);
pat.turnAround();
System.out.println(pat.numFlashersCollected());
Figure F-11 shows the path the robots take when this program is run. It
also shows the console window displaying the number of flashers each robot
collected.
This program requires two changes to the Collector class. First, it must
be modified to remember the number of flashers collected. Second, a query,
numFlashersCollected, must be added to retrieve the number so it can be
printed.
At first, we may think that all we need is a temporary variable to remem
ber the number of flashers a robot has collected. This will not work, how
ever, because a temporary variable exists only as long as the service containing
it executes – then the variable and the value it contained are gone. jasmine,
however, will execute collectFlashers twice before we ask for the number
of flashers collected. A temporary variable inside collectFlashers could
not keep a running total across both uses of the service.
F.7 Objects That Remember 493
Figure F-11: The result of running the modified program. Arrows show the path each robot
took.
variables can be used in any method in the class, we can write a separate
method that returns the current value of the instance variable. Third, because
each object has its own instance variable, jasmine and pat can each keep
track of their own work.
Listing F-14 shows how to use an instance variable named
flasherCount to remember how many flashers have been collected. The
only differences between Listing F-14 and the previous version in Listing F
12 are shown in bold.
Listing F-14: Modifications to Collector to remember the number of flashers collected.
1 import becker.robots.*;
5
6 public Collector(City city, int ave, int str, int dir)
7 { super(city, ave, str, dir);
8 }
9
10 public void collectFlashers(int numIntersections)
11 { int numMoves = 0;
12 while (numMoves < numIntersections - 1)
13 { this.pickFlasherIfPresent();
14 this.move();
15 numMoves = numMoves + 1;
16 }
17 this.pickFlasherIfPresent();
18 }
19
20 public void pickFlasherIfPresent()
21 { if (this.isBesideThing(Predicate.aFlasher))
22 { this.pickThing(Predicate.aFlasher);
23 this.flasherCount = this.flasherCount + 1;
24 }
25 }
26
27 public void turnAround()
28 { this.turnLeft();
29 this.turnLeft();
30 }
31
32 public int numFlashersCollected()
33 { return this.flasherCount;
34 }
35 }
flasherCount starts out with a value of 0 when the robot object is cre
ated. However, just after a flasher is picked up at line 22 the instance variable
is incremented. Incrementing flasherCount is very similar to incrementing
the temporary variable at line 15 – except that we use the keyword this to
emphasize that flasherCount is something that belongs to the object, much
like move, turnLeft, and collectFlashers belong to the object.
The code at lines 32-34 provide a query answering the question of how
many flashers the robot has collected so far. It is like other methods except
that it says what kind of answer it returns – an integer, abbreviated int. It
also includes an instruction to return the answer – the value contained in
flasherCount – to the client that called the query.
There are many times when an object may want to remember informa
tion for a long time. A robot may want to remember how far it has traveled
or the location of a Thing representing a pot of gold. An object representing
a bank account will need to remember the balance for as long as it exists. An
Employee object should remember the employee’s starting date and annual
salary, no matter which of many possible services is being executed – or even
if no service is being executed at the moment.
On the other hand, if the information is only needed in a single method,
an instance variable is more power than is needed. A temporary variable is
likely a better choice.
Predicate.aFlasher);
f.turnOff();
Figure F-12: Streets with two different kinds of lights, flashers and streetlights.
Similar code could be used to turn off a streetlight, except that we have to
specify that we are interested in Streetlight objects.
Streetlight s =
(Streetlight)this.examineThing(
Predicate.aStreetlight);
s.turnOff();
There is one restriction on this code. If the intersection does not actually
have a streetlight, the program will produce a run-time error when it tries to
turnoff the non-existent streetlight. One way to fix this problem is to use an
if statement to only execute this code if the robot is beside a streetlight.
These ideas can be combined to create a turnLightsOff method. It, to
gether with a helper method, are shown in Listing F-15.
The turnLightsOff method is very, very similar to the collect-
Flashers method. The difference is what happens on each intersection.
Instead of calling pickFlasherIfPresent, turnLightsOff calls the method
turnLightsOffHere.
When the turnLightsOffHere method executes, it first checks if the in
tersection has a flasher. If so, the robot gets the flasher and calls its turnOff
method. Then the robot checks for a streetlight. If there is a streetlight, the
robot gets it and calls its turnOff method.
F.8 The Same, But Different 497
2 { int numMoves = 0;
4 { this.turnLightsOffHere();
5 this.move();
6 numMoves = numMoves + 1;
7 }
8 this.turnLightsOffHere();
9 }
10
12 { if (this.isBesideThing(Predicate.aFlasher))
13 { Flasher f = (Flasher)this.examineThing(
14 Predicate.aFlasher);
15 f.turnOff();
16 }
17 if (this.isBesideThing(Predicate.aStreetlight))
18 { Streetlight s = (Streetlight)this.examineThing(
19 Predicate.aStreetlight);
20 s.turnOff();
21 }
22 }
It is no coincidence that flashers and streetlights are both turned off with
a method named turnOff. Recall from Section G.1 that we extended the
Robot class to create a new kind of robot, a Collector. A Collector robot
had all of the methods a regular Robot has: move, pickThing, putThing,
and so on. It was also customized to include a new method, collect-
Flashers.
Flasher and Streetlight both extend the class Light. The Light
class contains the methods turnOn and turnOff. The Flasher and
Streetlight classes both inherit these methods. Just as a Collector robot
can move, thanks to the move method inherited from Robot, a Flasher and a
Streetlight can be turned on or off, thanks to the turnOn and turnOff
methods inherited from Light.
Looking at these classes another way, Flasher and Streetlight are
both a kind of Light. Therefore, they must be able to be turned on and off.
This yields an interesting idea. Perhaps we can instruct the robot to ex
amine the intersection for a light. Not a flasher, in particular, nor a streetlight
in particular, but just a light.
498 Appendix F: The Lay of the Land
lite.turnOff();
2 { if (this.isBesideThing(Predicate.aLight))
In some ways, it is surprising that this code works. After all, there are
differences between streetlights and flashers. When a Streetlight is on, it
just shines gently. When a flasher is on, it flashes insistently. It seems rea
sonable that these differences in behavior would result in differences in the
turnOff methods – a streetlight would turn itself off differently than a
flasher would turn itself off.
This is the case. The definition of turnOff for a Streetlight is
public void turnOff()
{ this.setIcon(this.offIcon);
{ FlasherIcon fi = (FlasherIcon)this.getIcon();
fi.stop();
this.on = false;
also different – they turn off in different ways. This concept of having the
same service behave differently, depending on the class, is called polymorphism.
Polymorphism is useful when you have different kinds of objects that
need to perform variations of the same basic action. For example, you might
have two different kinds of dancing robots. A left-dancing robot moves to
the left, forward, and then back to the right when sent the move message. A
right-dancing robot moves to the right, forward, and then to the left when it
moves. Both respond to the move message, but move differently.
As another example, consider an Employee class that is extended in two
different ways: HourlyEmployee and SalariedEmployee. Every Employee
should have a calcWages method, but HourlyEmployee and
SalariedEmployee calculate the answer differently. Fortunately, the code
Employee e = (Employee)this.getNextEmployee();
e.calcWage();
selected.play();
F.9 Collections
The original paving job is finished and the construction company has landed
another contract. This time the contract is much larger – a huge subdivision
consisting of fifty streets. As before, robots are required to collect the flash
ers from the intersections each morning.
Working with fifty robots on fifty streets raises two issues. First is the te
dium of coming up with the names for fifty robots. Second is the large
amount of code that is exactly the same except for the name of the robot in
volved.
500 Appendix F: The Lay of the Land
Using only the techniques we have learned so far, the main program
would have to be written as shown in Listing F-17.
Listing F-17: A naïve program directing 50 robots to collect flashers on 50 streets.
1 import becker.robots.*;
4 {
5 public static void main(String[] args)
6 { ConSite site = new ConSite();
7
8 Collector worker_0 =
9 new Collector(site, 1, 1, Directions.EAST);
10 Collector worker_1 =
11 new Collector(site, 1, 2, Directions.EAST);
12 Collector worker_2 =
13 new Collector(site, 1, 3, Directions.EAST);
14 ... // many workers omitted
15 Collector worker_48 =
16 new Collector(site, 1, 49, Directions.EAST);
17 Collector worker_49 =
18 new Collector(site, 1, 50, Directions.EAST);
19
20 CityFrame frame = new CityFrame(site);
21
22 worker_0.collectFlashers();
23 worker_0.turnAround();
24 worker_1.collectFlashers();
25 worker_1.turnAround();
26 worker_2.collectFlashers();
27 worker_2.turnAround();
28 ... // many workers omitted
29 worker_48.collectFlashers();
30 worker_48.turnAround();
31 worker_49.collectFlashers();
32 worker_49.turnAround();
33 }
34 }
Using numbers in the names of the robots makes the similarity of many
lines obvious. One might wonder if we can make use of all that similarity.
If fact, we can. There are various ways to collect many objects, such as
robots, together. The result is called a collection. Collections are used by giving
the name of the collection together with a number. For example, suppose the
collection is named workers and already contains the fifty robots. Then the
fifth robot could be told to collect flashers and turn around with the follow
ing code:
F.9 Collections 501
worker.collectFlashers();
worker.turnAround();
This doesn’t seem to be useful until we realize that the 5 can be replaced
with a variable. If we put these three lines inside a loop that counts from 0 to
49, then 50 robots will collect flashers and then turnaround! All with just the
following 7 lines of code (instead of the 100 required in Listing F-17).
int workerNum = 0;
worker.collectFlashers();
worker.turnAround();
workerNum = workerNum + 1;
The beauty of this approach is that 1,000 robots could be told to collect
flashers with the same seven lines of code. Only the 50 in the second line
would need to change.
Collections are often used in programs. Each robot uses a collection to Collections are used when
lots of similar information
implement its “backpack” and the City class uses a collection to manage all must be managed.
the things it contains – robots, walls, flashers, and so on. Programs used at a
bank use collections to keep track of all the different Account objects and
payroll programs use collections of Employee objects. Word processors use
collections to store many Paragraph objects and all the words in the spelling
checker’s dictionary.
Any time a program must use many similar objects or similar pieces of in
formation, a collection is probably being used.