Survey
* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
Chapter 8
Polymorphism and Abstract Classes
Key Terms
late binding, p. 477
binding, p. 477
early binding, p. 477
polymorphism, p. 478
final, p. 479
upcasting, p. 492
downcasting, p. 492
instanceOf, p. 493
clone, p. 496
abstract method, p. 502
abstract cannot be private, p. 505
abstract class, p. 505
concrete class, p. 505
Brief Outline
8.1 Polymorphism
Late Binding
The final Modifier
Late Binding with toString
Downcasting and Upcasting
A First Look at the clone Method
8.2 Abstract Classes
Abstract Classes
List of Displays
Displays
Display 8.1 The Base Class Sale, p. 481 - 483
Display 8.2 The Derived Class DiscoutSale, p. 484 - 485
Display 8.3 Late Binding Demonstration, p. 486
Display 8.4 No Late Binding with Static Methods, p. 490
Display 8.5 Copy Constructor Versus clone Method, p. 500 - 501
Display 8.6 Employee Class and its Derived Classes, p. 503 - 504
Display 8.7 Employee Class as an Abstract Class, p. 506
Teaching Suggestions
This chapter discusses polymorphism. The concept of polymorphism is one that is sometimes
hard for students to grasp. As indicated, this chapter does not require any information from
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
Chapter 6 and could be taught before that. However, inheritance is required, so a possible
reordering of topics could be Chapters 7 & 8 before Chapter 6.
In this section, we also see the introduction of abstract classes. An abstract class is one that is at
least partially undefined within the program. The programmer can not create an instance of an
abstract class and these classes can be used as a basis of an inheritance hierarchy. When a class
extends an abstract class, the subclass is required to give a definition to the abstract methods or
be declared abstract. This is compiler enforced.
These two topics in this chapter are somewhat disjoint and the instructor may choose to cover
them at separate times as one does not need polymorphism to have an abstract class or have an
abstract class to use polymorphism.
Key Points
Late Binding. Java uses late binding for all method calls, which is what makes polymorphism
possible. This concept deals with how the machine actually handles the call to the method at the
system level.
Polymorphism. The main idea of polymorphism is the ability to associate many meanings to one
method, making the method execute differently depending on in what context the method is
called.
The final Modifier. Adding final to a method definition means that a method can not be
redefined in any subclass. If a class is declared final, it can not be used as a superclass.
An Object Knows the Definitions of its Methods. The only methods that can be called on an
object are those that are defined by its class type. The method that will get executed is the one
that is defined by its object type.
Abstract Method. An abstract method is one that is not defined in a particular class. The entire
method signature is given with a semicolon where the method body should be. Also indicative
of an abstract method is the keyword abstract in the method signature. Classes that subclass
from a class with an abstract method are forced by the compiler to provide a definition for the
abstract method.
Abstract Class. As soon as a class has an abstract method, the entire class becomes abstract
indicated by the keyword abstract in the class definition.
Tips
Checking to See if Downcasting is Legitimate. This tip is optional and omitting it will not hinder
students trying to understand polymorphism. The discussion focuses on using the instanceof
operator to see if downcasting makes sense in a particular case.
An Abstract Class is a Type. Even though you cannot create an instance of an abstract class, you
can still use it as a type of a variable or as a type for a parameter or return type. There is a tip in
this section that reiterates this same idea.
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
Pitfalls
No Late Binding for Static Methods. Java does not use late binding for private methods, methods
that are final, or static methods. This is most important for static methods. When methods are
static, Java uses static binding and the method’s execution is determined at compile time, which
may or may not be what the programmer had originally intended.
Downcasting. It is the programmer’s responsibility to use downcasting when necessary.
However, if the programmer uses downcasting in the incorrect place, a run time error will
usually be thrown.
Sometimes the clone Method Return Type is Object. The clone method is inherited from the
class Object and when you are writing a clone method in an object, you must give its return type
as Object. If you give another return type, a compiler error will be thrown because you cannot
use method overloading on a method by only changing the return type.
Limitations of Copy Constructor. This pitfall is another optional section and talks about why the
copy constructor is not always the best choice. In fact, the clone method is the preferred method
for doing the copy constructor functionality in Java. Therefore, this discussion could be relevant
for why clone should be used. Alternatively, an instructor could choose not to discuss a copy
constructor, but rather just wait to discuss the clone method.
You Cannot Create Instances of an Abstract Class. This pitfall is pretty self explanatory. The
compiler will simply not allow this to happen.
Examples
Sales Records. In this example we see how late binding is used when calling the bill method of
the Sale class. It also introduces the idea that as software designers, we may not always have
perfect information about a problem. We can not always see all the possible ways a program
will be used when built and one way to possibly help our programs be more versatile is to
harness the power of polymorphism.
Programming Projects Answers
1.
/**
* Question1AlienAbstract.java
*
* This program introduces inheritance by rewriting a non-OO class
* using a switch statement for types into one with derived classes
* for the subtypes. A getDamage method returns the amount of
* damage that an alien inflicts. This design is superior to the
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
* old one since it is now independent to add a new type of Alien
* to the game; we no longer need to change code in the Alien class.
*
* In this version, the Alien class has been turned into an abstract
* class.
*
* Created: Sat Mar 19 2005
*
* @author Kenrick Mock
* @version 1
*/
abstract class Alien {
private int health; // 0=dead, 100=full strength
private String name;
/**
* Default constructor; Initialize name and health.
*/
public Alien()
{
health = 100;
name = "";
}
/**
* Default constructor; Initialize variables to input parameters.
* @param health Initial health
* @param name Initial name
*/
public Alien(int health, String name)
{
this.health = health;
this.name = name;
}
// ======================
// Various accessor and mutator methods
// ======================
public int getHealth()
{
return health;
}
public void setHealth(int health)
{
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
this.health = health;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
/**
* getDamage returns the amount of damage this alien inflicts.
*/
public abstract int getDamage();
} // Alien
/** The SnakeAlien class extends the Alien class
* since it is a sub-type of Alien. By doing this for
* all the alien types, we can eliminate the "type" variable
* in the original Alien class.
*/
class SnakeAlien extends Alien
{
public static final int SNAKE_DAMAGE = 10;
/**
* Constructors
*/
public SnakeAlien()
{
super();
}
public SnakeAlien(int health, String name)
{
super(health,name);
}
/**
* getDamage returns the amount of damage this alien inflicts.
*/
public int getDamage()
{
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
return SNAKE_DAMAGE;
}
} // SnakeAlien
/**
* Class for the Ogre Alien
*/
class OgreAlien extends Alien
{
public static final int OGRE_DAMAGE = 6;
/**
* Constructors
*/
public OgreAlien()
{
super();
}
public OgreAlien(int health, String name)
{
super(health,name);
}
/**
* getDamage returns the amount of damage this alien inflicts.
*/
public int getDamage()
{
return OGRE_DAMAGE;
}
} // OgreAlien
/**
* Class for the Marshmallow Alien
*/
class MarshmallowAlien extends Alien
{
public static final int MARSHMALLOW_DAMAGE = 1;
/**
* Constructors
*/
public MarshmallowAlien()
{
super();
}
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
public MarshmallowAlien(int health, String name)
{
super(health,name);
}
/**
* getDamage returns the amount of damage this alien inflicts.
*/
public int getDamage()
{
return MARSHMALLOW_DAMAGE;
}
} // MarshmallowAlien
/**
* This class stores an array of Aliens that comprise a "pack"
*/
class AlienPack {
private Alien[] aliens;
public AlienPack(int numAliens) {
aliens = new Alien[numAliens];
}
public void addAlien(Alien newAlien, int index) {
aliens[index] = newAlien;
}
public Alien[] getAliens() {
return aliens;
}
/**
* To calculate the damage inflicted by all aliens in the pack
* we can now simply iterate through each alien and call its
* getDamage() method
*/
public int calculateDamage() {
int damage = 0;
for (int i=0; i < aliens.length; i++)
{
damage += aliens[i].getDamage();
}
return damage;
}
} // AlienPack
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
class Question1AlienAbstract
{
/** ======================
* main method.
* In main we simply create a small pack and output its total damage (17).
* ======================
*/
public static void main(String[] args)
{
OgreAlien brutus = new OgreAlien(100,"brutus");
SnakeAlien slimy = new SnakeAlien(100,"slimy");
MarshmallowAlien puffy = new MarshmallowAlien(100,"puffy");
AlienPack pack = new AlienPack(3); // 3 aliens in the pack
pack.addAlien(brutus, 0);
pack.addAlien(slimy, 1);
pack.addAlien(puffy, 2);
System.out.println("Total pack damage = " + pack.calculateDamage());
}
} // Question1AlienAbstract
2.
/**
* Question2Movie.java
*
* This program introduces inheritance by creating subclasses of
* a Movie class. We override the equals() and calcLateFees()
* methods.
*
* Created: Sat Mar 19 2005
*
* @author Kenrick Mock
* @version 1
*/
class Movie {
private int MovieID;
private String title;
private String rating;
// e.g. "G", "PG-13", "R"
/**
* Default constructor; Initialize private variables.
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
*/
public Movie()
{
MovieID = 0;
title = "";
rating = "";
}
/**
* Default constructor; Initialize variables to input parameters.
* @param title Initial title
* @param ID Initial ID
* @param rating Initial rating
*/
public Movie(int ID, String title, String rating)
{
this.MovieID = ID;
this.title = title;
this.rating = rating;
}
// ======================
// Various accessor and mutator methods
// ======================
public int getID()
{
return MovieID;
}
public void setID(int ID)
{
this.MovieID = ID;
}
public String getTitle()
{
return title;
}
public void setTitle(String name)
{
this.title = name;
}
public String getRating()
{
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
return rating;
}
public void setRating(String rating)
{
this.rating = rating;
}
/**
* Define equals where the ID's match
*/
public boolean equals(Object other)
{
if (other == null)
return false;
else if (getClass() != other.getClass())
return false;
else
{
Movie otherMovie = (Movie) other;
if (otherMovie.getID() == this.getID()) return true;
}
return false;
}
/**
* calcLateFees returns the default cost in late fees, $2/day
* @param daysLate the number of days the movie is late
*/
public double calcLateFees(int daysLate)
{
return (2.0 * daysLate);
}
} // Movie
/** The ActionMovie class extends the Movie class
* since it is a sub-type of Movie.
*/
class ActionMovie extends Movie
{
/**
* Constructors
*/
public ActionMovie()
{
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
super();
}
public ActionMovie(int ID, String title, String rating)
{
super(ID, title, rating);
}
/**
* calcLateFees returns the cost in late fees for action flicks, $3/day
*
* @param daysLate the number of days the movie is late
*/
public double calcLateFees(int daysLate)
{
return (3.0 * daysLate);
}
} // ActionMovie
/** The ComedyMovie class extends the Movie class
* since it is a sub-type of Movie.
*/
class ComedyMovie extends Movie
{
/**
* Constructors
*/
public ComedyMovie()
{
super();
}
public ComedyMovie(int ID, String title, String rating)
{
super(ID, title, rating);
}
/**
* calcLateFees returns the cost in late fees for comedy flicks, $2.50/day
*
* @param daysLate the number of days the movie is late
*/
public double calcLateFees(int daysLate)
{
return (2.5 * daysLate);
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
}
} // ComedyMovie
/** The DramaMovie class extends the Movie class
* since it is a sub-type of Movie.
*/
class DramaMovie extends Movie
{
/**
* Constructors
*/
public DramaMovie()
{
super();
}
public DramaMovie(int ID, String title, String rating)
{
super(ID, title, rating);
}
/**
* calcLateFees is not defined here, so it will just
* use the default version provided by Movie of $2/day
*/
} // DramaMovie
class Question2Movie
{
/** ======================
* main method.
* In main we simply create some sample movies and output the late fees.
* We also test the equals method on our sample movies.
* ======================
*/
public static void main(String[] args)
{
ActionMovie killbill2 = new ActionMovie(0,
"Kill Bill: Volume 2", "R");
ComedyMovie meangirls = new ComedyMovie(1,
"Mean Girls", "PG-13");
DramaMovie mystic = new DramaMovie(2,
"Mystic River", "R");
DramaMovie mysticCopy2 = new DramaMovie(2,
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
"Mystic River, Second Copy", "R");
System.out.println("If " + killbill2.getTitle() +
" is 2 days late the fee is " +
killbill2.calcLateFees(2));
System.out.println("If " + killbill2.getTitle() +
" is 3 days late the fee is " +
killbill2.calcLateFees(3));
System.out.println("If " + meangirls.getTitle() +
" is 3 days late the fee is " +
meangirls.calcLateFees(3));
System.out.println("If " + mystic.getTitle() +
" is 3 days late the fee is " +
mystic.calcLateFees(3));
// Test our equals method
System.out.println("Is " + killbill2.getTitle() +
" equal " + mystic.getTitle() +
"? " + killbill2.equals(mystic));
System.out.println("Is " + meangirls.getTitle() +
" equal " + mystic.getTitle() +
"? " + meangirls.equals(mystic));
System.out.println("Is " + mystic.getTitle() +
" equal " + mysticCopy2.getTitle() +
"? " + mystic.equals(mysticCopy2));
}
} // Question2Movie
3.
/**
* Question3Rental.java
*
* This program uses the Movie class to track an array of rentals.
*
* Created: Sat Mar 19 2005
*
* @author Kenrick Mock
* @version 1
*/
class Movie {
private int MovieID;
private String title;
private String rating;
// e.g. "G", "PG-13", "R"
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
/**
* Default constructor; Initialize private variables.
*/
public Movie()
{
MovieID = 0;
title = "";
rating = "";
}
/**
* Default constructor; Initialize variables to input parameters.
* @param title Initial title
* @param ID Initial ID
* @param rating Initial rating
*/
public Movie(int ID, String title, String rating)
{
this.MovieID = ID;
this.title = title;
this.rating = rating;
}
// ======================
// Various accessor and mutator methods
// ======================
public int getID()
{
return MovieID;
}
public void setID(int ID)
{
this.MovieID = ID;
}
public String getTitle()
{
return title;
}
public void setTitle(String name)
{
this.title = name;
}
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
public String getRating()
{
return rating;
}
public void setRating(String rating)
{
this.rating = rating;
}
/**
* Define equals where the ID's match
*/
public boolean equals(Object other)
{
if (other == null)
return false;
else if (getClass() != other.getClass())
return false;
else
{
Movie otherMovie = (Movie) other;
if (otherMovie.getID() == this.getID()) return true;
}
return false;
}
/**
* calcLateFees returns the default cost in late fees, $2/day
* @param daysLate the number of days the movie is late
*/
public double calcLateFees(int daysLate)
{
return (2.0 * daysLate);
}
} // Movie
/** The ActionMovie class extends the Movie class
* since it is a sub-type of Movie.
*/
class ActionMovie extends Movie
{
/**
* Constructors
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
*/
public ActionMovie()
{
super();
}
public ActionMovie(int ID, String title, String rating)
{
super(ID, title, rating);
}
/**
* calcLateFees returns the cost in late fees for action flicks, $3/day
*
* @param daysLate the number of days the movie is late
*/
public double calcLateFees(int daysLate)
{
return (3.0 * daysLate);
}
} // ActionMovie
/** The ComedyMovie class extends the Movie class
* since it is a sub-type of Movie.
*/
class ComedyMovie extends Movie
{
/**
* Constructors
*/
public ComedyMovie()
{
super();
}
public ComedyMovie(int ID, String title, String rating)
{
super(ID, title, rating);
}
/**
* calcLateFees returns the cost in late fees for comedy flicks, $2.50/day
*
* @param daysLate the number of days the movie is late
*/
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
public double calcLateFees(int daysLate)
{
return (2.5 * daysLate);
}
} // ComedyMovie
/** The DramaMovie class extends the Movie class
* since it is a sub-type of Movie.
*/
class DramaMovie extends Movie
{
/**
* Constructors
*/
public DramaMovie()
{
super();
}
public DramaMovie(int ID, String title, String rating)
{
super(ID, title, rating);
}
/**
* calcLateFees is not defined here, so it will just
* use the default version provided by Movie of $2/day
*/
} // DramaMovie
/**
* This class tracks who rented what movie
* and how many days late it is.
*/
class Rental
{
private Movie movie;
private int CustomerID;
private int daysLate;
/**
* Constructors
*/
public Rental()
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
{
CustomerID=0;
daysLate=0;
movie=null;
}
public Rental(Movie movie, int ID)
{
CustomerID=ID;
daysLate=0;
this.movie=movie;
}
// ======================
// Accessor and mutator methods
// ======================
public int getCustomerID()
{
return CustomerID;
}
public void setCustomerID(int ID)
{
CustomerID = ID;
}
public int getDaysLate()
{
return daysLate;
}
public void setDaysLate(int daysLate)
{
this.daysLate = daysLate;
}
public Movie getMovie()
{
return this.movie;
}
public void setMovie(Movie movie)
{
this.movie = movie;
}
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
/**
* This method invokes calcLateFees from the Movie
* class to get the late fee charge
*/
public double getLateFees()
{
return movie.calcLateFees(daysLate);
}
} // Rental
/**
* The Question3Rental class keeps an array of rentals.
* We can then track all of our rentals conveniently
* in one array.
*/
class Question3Rental
{
private Rental[] rentals;
/**
* Constructor sets the size of the array.
*/
public Question3Rental(int numRentals)
{
rentals = new Rental[numRentals];
}
/**
* setRental stores a reference to a Rental object
* at the specified index.
* @param rental The rental object to put in the array
* @param index the position in the array to place the object
*/
public void setRental(Rental rental, int index)
{
this.rentals[index] = rental;
}
/**
* Return array of rentals
* @return Rental[] array of rentals
*/
public Rental[] getRentals()
{
return this.rentals;
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
}
/**
* Iterate through the rental array and calculate
* the total amount of late fees.
*/
public double lateFeesOwed()
{
double amount=0;
for (int i=0; i<rentals.length; i++)
{
amount+=rentals[i].getLateFees();
}
return amount;
}
/** ======================
* main method.
* In main we simply create some sample movies and output the late fees.
* ======================
*/
public static void main(String[] args)
{
ActionMovie killbill2 = new ActionMovie(0, "Kill Bill: Volume 2", "R");
ComedyMovie meangirls = new ComedyMovie(1, "Mean Girls", "PG-13");
DramaMovie mystic = new DramaMovie(2, "Mystic River", "R");
Question3Rental JoesRentals = new Question3Rental(3); // Joe is ID #1
Rental rental1 = new Rental(killbill2, 1);
Rental rental2 = new Rental(meangirls, 1);
Rental rental3 = new Rental(mystic, 1);
JoesRentals.setRental(rental1, 0);
// Add rentals to array
JoesRentals.setRental(rental2, 1);
JoesRentals.setRental(rental3, 2);
// Make each movie 2 days late
rental1.setDaysLate(2);
rental2.setDaysLate(2);
rental3.setDaysLate(2);
// Calculate late fees
System.out.println("With each movie 2 days late the late fees are " +
JoesRentals.lateFeesOwed());
}
} // Question3Rental
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
4.
/**
* Question4Simulation.java
*
* This program simulates a 2D world with predators and prey.
* The predators (doodlebugs) and prey (ants) inherit from the
* Organism class that keeps track of basic information about each
* critter (time ticks since last bred, position in the world).
*
* The 2D world is implemented as a separate class, World,
* that contains a 2D array of pointers to type Organism.
*
* Created: Sat Mar 19 2005
*
* @author Kenrick Mock
* @version 1
*/
import java.util.Scanner;
/**
* The World class stores data about the world by creating a
* WORLDSIZE by WORLDSIZE array of type Organism.
* null indicates an empty spot, otherwise a valid object
* indicates an ant or doodlebug. To determine which,
* invoke the virtual function getType of Organism that should return
* ANT if the class is of type ant, and DOODLEBUG otherwise.
*/
class World
{
public static final int WORLDSIZE = 20;
private Organism[][] grid;
// Array of organisms for each cell
/**
* Default constructor; Initialize the world to NULL's.
*/
public World()
{
// Initialize world to empty spaces
int i,j;
grid = new Organism[WORLDSIZE][WORLDSIZE];
for (i=0; i<WORLDSIZE; i++)
{
for (j=0; j<WORLDSIZE; j++)
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
{
grid[i][j]=null;
}
}
}
/**
* getAt
* Returns the entry stored in the grid array at x,y.
* @param x X coordinate of the cell to retrieve
* @param y Y coordinate of the cell to retrieve
*/
public Organism getAt(int x, int y)
{
if ((x>=0) && (x<World.WORLDSIZE) && (y>=0) &&
(y<World.WORLDSIZE))
return grid[x][y];
return null;
}
/**
* setAt
* Sets the entry in the grid array at x,y to the input organism
* @param x X coordinate of the cell to store
* @param y Y coordinate of the cell to store
* @param org Organism object to store in the grid
*/
public void setAt(int x, int y, Organism org)
{
if ((x>=0) && (x<World.WORLDSIZE) && (y>=0) &&
(y<World.WORLDSIZE))
{
grid[x][y] = org;
}
}
/**
* Display
* Displays the world in ASCII.text
*/
public void Display()
{
int i,j;
System.out.println();
System.out.println();
for (j=0; j<World.WORLDSIZE; j++)
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
{
for (i=0; i<World.WORLDSIZE; i++)
{
if (grid[i][j]==null)
System.out.print(".");
else
System.out.print(grid[i][j].getPrintableChar());
// X for Doodle, o for Ant
}
System.out.println();
}
}
/**
* SimulateOneStep
* This is the main routine that simulates one turn in the world.
* First, a flag for each organism is used to indicate if it has moved.
* This is because we iterate through the grid starting from the top
* looking for an organism to move . If one moves down, we don't want
* to move it again when we reach it.
* First move doodlebugs, then ants, and if they are still alive then
* we breed them.
*/
public void SimulateOneStep()
{
int i,j;
// First reset all organisms to not moved
for (i=0; i<World.WORLDSIZE; i++)
for (j=0; j<World.WORLDSIZE; j++)
{
if (grid[i][j]!=null) grid[i][j].setMoved(false);
}
// Loop through cells in order and move if it's a Doodlebug
for (i=0; i<World.WORLDSIZE; i++)
for (j=0; j<World.WORLDSIZE; j++)
{
if ((grid[i][j]!=null) && (grid[i][j] instanceof Doodlebug))
{
if (grid[i][j].getMoved() == false)
{
grid[i][j].setMoved(true); // Mark as moved
grid[i][j].move();
}
}
}
// Loop through cells in order and move if it's an Ant
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
for (i=0; i<World.WORLDSIZE; i++)
for (j=0; j<World.WORLDSIZE; j++)
{
if ((grid[i][j]!=null) && (grid[i][j] instanceof Ant))
{
if (grid[i][j].getMoved() == false)
{
grid[i][j].setMoved(true); // Mark as moved
grid[i][j].move();
}
}
}
// Loop through cells in order and check if anyone is starving
for (i=0; i<World.WORLDSIZE; i++)
for (j=0; j<World.WORLDSIZE; j++)
{
// Kill off any doodlebugs that haven't eaten recently
if ((grid[i][j]!=null) &&
(grid[i][j] instanceof Doodlebug))
{
if (grid[i][j].starve())
{
grid[i][j] = null;
}
}
}
// Loop through cells in order and check if we should breed
for (i=0; i<World.WORLDSIZE; i++)
for (j=0; j<World.WORLDSIZE; j++)
{
// Only breed organisms that have moved, since
// breeding places new organisms on the map we
// don't want to try and breed those
if ((grid[i][j]!=null) && (grid[i][j].getMoved()))
{
grid[i][j].breed();
}
}
}
} // World
/**
* Definition for the Organism base class.
* Each organism has a reference back to
* the World object so it can move itself
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
* about in the world.
*/
abstract class Organism
{
protected int x,y;
protected boolean moved;
protected int breedTicks;
protected World world;
// Position in the world
// Bool to indicate if moved this turn
// Number of ticks since breeding
// Reference to the world object so we can update its
// grid when we move around in the world
/**
* Constructors
*/
public Organism()
{
world = null;
moved = false;
breedTicks = 0;
x=0;
y=0;
}
public Organism(World world, int x, int y)
{
this.world = world;
moved = false;
breedTicks = 0;
this.x=x;
this.y=y;
world.setAt(x,y,this);
}
/**
* Accessor/Mutator for the Moved variable
*/
public boolean getMoved()
{
return moved;
}
public void setMoved(boolean moved)
{
this.moved = moved;
}
/**
* Determines whether or not this organism should breed
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
*/
public abstract void breed();
/**
* Determines how this organism should move
*/
public abstract void move();
/**
* Determines if this organism starves
*/
public abstract boolean starve();
/**
* Returns a symbol for the organism
*/
public abstract String getPrintableChar();
} // Organism
/**
* Start with the Ant class
*/
class Ant extends Organism
{
public static final int ANTBREED = 3;
// How many ticks to breed an ant
/**
* Constructors
*/
public Ant()
{
super();
}
public Ant(World world, int x, int y)
{
super(world,x,y);
}
/**
* Ant breed
* Increment the tick count for breeding.
* If it equals our threshold, then clone this ant either
* above, right, left, or below the current one.
*/
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
public void breed()
// Must define this since virtual
{
breedTicks++;
if (breedTicks == ANTBREED)
{
breedTicks = 0;
// Try to make a new ant either above, left, right, or down
if ((y>0) && (world.getAt(x,y-1)==null))
{
Ant newAnt = new Ant(world, x, y-1);
}
else if ((y<World.WORLDSIZE-1) && (world.getAt(x,y+1)==null))
{
Ant newAnt = new Ant(world, x, y+1);
}
else if ((x>0) && (world.getAt(x-1,y)==null))
{
Ant newAnt = new Ant(world, x-1, y);
}
else if ((x<World.WORLDSIZE-1) && (world.getAt(x+1,y)==null))
{
Ant newAnt = new Ant(world, x+1, y);
}
}
}
/**
* Ant Move
* Look for an empty cell up, right, left, or down and
* try to move there.
*/
public void move()
// Must define this since virtual
{
// Pick random direction to move
int dir = (int) (Math.random() * 4);
// Try to move up, if not at an edge and empty spot
if (dir==0)
{
if ((y>0) && (world.getAt(x,y-1)==null))
{
world.setAt(x,y-1,world.getAt(x,y)); // Move to new spot
world.setAt(x,y,null);
y--;
}
}
// Try to move down
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
else if (dir==1)
{
if ((y<World.WORLDSIZE-1) && (world.getAt(x,y+1)==null))
{
world.setAt(x,y+1,world.getAt(x,y)); // Move to new spot
world.setAt(x,y,null); // Set current spot to empty
y++;
}
}
// Try to move left
else if (dir==2)
{
if ((x>0) && (world.getAt(x-1,y)==null))
{
world.setAt(x-1,y,world.getAt(x,y)); // Move to new spot
world.setAt(x,y,null); // Set current spot to empty
x--;
}
}
// Try to move right
else
{
if ((x<World.WORLDSIZE-1) && (world.getAt(x+1,y)==null))
{
world.setAt(x+1,y,world.getAt(x,y)); // Move to new spot
world.setAt(x,y,null); // Set current spot to empty
x++;
}
}
}
/**
* Return false since an ant never starves
*/
public boolean starve()
{
return false;
}
/**
* an Ant is represented by "o"
*/
public String getPrintableChar()
{
return "o";
}
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
} // Ant
/**
* Now define Doodlebug Class
*/
class Doodlebug extends Organism
{
public static final int DOODLEBREED = 8;
public static final int DOODLESTARVE = 3;
private int starveTicks;
// Ticks to breed
// Ticks to starve
// Number of moves since last feeding
/**
* Constructors
*/
public Doodlebug()
{
super();
starveTicks = 0;
}
public Doodlebug(World world, int x, int y)
{
super(world,x,y);
starveTicks = 0;
}
/**
* Doodlebug breed
* Creates a new doodlebug adjacent to the current cell
* if the breedTicks meets the threshold.
*/
public void breed() // Must define this since virtual
{
breedTicks++;
if (breedTicks == DOODLEBREED)
{
breedTicks = 0;
// Try to make a new ant either above, left, right, or down
if ((y>0) && (world.getAt(x,y-1)==null))
{
Doodlebug newDoodle = new Doodlebug(world, x, y-1);
}
else if ((y<World.WORLDSIZE-1) && (world.getAt(x,y+1)==null))
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
{
Doodlebug newDoodle = new Doodlebug(world, x, y+1);
}
else if ((x>0) && (world.getAt(x-1,y)==null))
{
Doodlebug newDoodle = new Doodlebug(world, x-1, y);
}
else if ((x<World.WORLDSIZE-1) && (world.getAt(x+1,y)==null))
{
Doodlebug newDoodle = new Doodlebug(world, x+1, y);
}
}
}
/**
* Doodlebug move
* Look up, down, left or right for a bug. If one is found, move there
* and eat it, resetting the starveTicks counter.
*/
public void move() // Must define this since virtual
{
// Look in each direction and if a bug is found move there
// and eat it.
if ((y>0) && (world.getAt(x,y-1)!=null) &&
(world.getAt(x,y-1) instanceof Ant))
{
world.setAt(x,y-1,this); // Move to spot
world.setAt(x,y,null);
starveTicks =0 ;
// Reset hunger
y--;
return;
}
else if ((y<World.WORLDSIZE-1) && (world.getAt(x,y+1)!=null) &&
(world.getAt(x,y+1) instanceof Ant))
{
world.setAt(x,y+1,this);
// Move to spot
world.setAt(x,y,null);
starveTicks =0;
// Reset hunger
y++;
return;
}
else if ((x>0) && (world.getAt(x-1,y)!=null) &&
(world.getAt(x-1,y) instanceof Ant))
{
world.setAt(x-1,y,this); // Move to spot
world.setAt(x,y,null);
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
starveTicks =0 ;
x--;
return;
// Reset hunger
}
else if ((x<World.WORLDSIZE-1) && (world.getAt(x+1,y)!=null) &&
(world.getAt(x+1,y) instanceof Ant))
{
world.setAt(x+1,y,this); // Move to spot
world.setAt(x,y,null);
starveTicks =0 ;
// Reset hunger
x++;
return;
}
// If we got here, then we didn't find food. Move
// to a random spot if we can find one.
int dir = (int) (Math.random() * 4);
// Try to move up, if not at an edge and empty spot
if (dir==0)
{
if ((y>0) && (world.getAt(x,y-1)==null))
{
world.setAt(x,y-1,world.getAt(x,y)); // Move to new spot
world.setAt(x,y,null);
y--;
}
}
// Try to move down
else if (dir==1)
{
if ((y<World.WORLDSIZE-1) && (world.getAt(x,y+1)==null))
{
world.setAt(x,y+1,world.getAt(x,y)); // Move to new spot
world.setAt(x,y,null); // Set current spot to empty
y++;
}
}
// Try to move left
else if (dir==2)
{
if ((x>0) && (world.getAt(x-1,y)==null))
{
world.setAt(x-1,y,world.getAt(x,y)); // Move to new spot
world.setAt(x,y,null); // Set current spot to empty
x--;
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
}
}
// Try to move right
else
{
if ((x<World.WORLDSIZE-1) && (world.getAt(x+1,y)==null))
{
world.setAt(x+1,y,world.getAt(x,y)); // Move to new spot
world.setAt(x,y,null); // Set current spot to empty
x++;
}
}
starveTicks++;
// Increment starve tick since we didn't
// eat on this turn
}
/**
* Doodlebug starve
* Returns true or false if a doodlebug should die off
* because it hasn't eaten enough food.
*/
public boolean starve()
// Check if a doodlebug starves to death
{
// Starve if no food eaten in last DOODLESTARVE time ticks
if (starveTicks > DOODLESTARVE)
{
return true;
}
else
{
return false;
}
}
/**
* Doodlebug represented by "X"
*/
public String getPrintableChar()
{
return "X";
}
} // Doodlebug
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
class Question4Simulation
{
public static final int INITIALANTS = 100;
public static final int INITIALBUGS = 5;
// ======================
// main method
// ======================
public static void main(String[] args)
{
String s;
World w = new World();
Scanner scan = new Scanner(System.in);
// Randomly create 100 ants
int antcount = 0;
while (antcount < INITIALANTS)
{
int x = (int) (Math.random() * World.WORLDSIZE);
int y = (int) (Math.random() * World.WORLDSIZE);
if (w.getAt(x,y)==null)
// Only put ant in empty spot
{
antcount++;
Ant a1 = new Ant(w,x,y);
}
}
// Randomly create 5 doodlebugs
int doodlecount = 0;
while (doodlecount < INITIALBUGS)
{
int x = (int) (Math.random() * World.WORLDSIZE);
int y = (int) (Math.random() * World.WORLDSIZE);
if (w.getAt(x,y)==null)
// Only put doodlebug in empty spot
{
doodlecount++;
Doodlebug d1 = new Doodlebug(w,x,y);
}
}
// Run simulation forever, until user cancels
while (true)
{
w.Display();
w.SimulateOneStep();
System.out.println("Press enter for next step");
s = scan.nextLine();
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
}
}
} // Question4Simulation
5.
/**
* Figure.java
*
*
* Created: Tue Jan 13 19:41:56 2004
*
* @author Adrienne Decker
* @version
*/
public class Figure
{
public Figure ()
{
System.out.println("Creating a figure with no parameters.");
}
public void erase()
{
System.out.println("Call to Figure's erase method.");
}
public void draw()
{
System.out.println("Call to Figure's draw method.");
}
public void center()
{
System.out.println("Calling Figure's center method.");
this.erase();
this.draw();
}
}// Figure
/**
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
* Rectangle.java
*
*
* Created: Tue Jan 13 19:48:48 2004
*
* @author Adrienne Decker
* @version
*/
public class Rectangle extends Figure
{
private int _width;
private int _height;
public Rectangle ()
{
System.out.println("Creating Rectangle Class with no parameters.");
_width = 0;
_height = 0;
}
public Rectangle(Rectangle other)
{
System.out.println("Creating Rectangle Class from another "
+ "Rectangle.");
_width = other._width;
_height = other._height;
}
public Rectangle(int width, int height)
{
System.out.println("Creating Rectangle Class given width and " +
"height.");
_width = width;
_height = height;
}
public void draw()
{
System.out.println("Calling Rectangle's draw method.");
}
public void erase()
{
System.out.println("Calling Rectangle's erase method.");
}
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
}// Rectangle
/**
* Triangle.java
*
*
* Created: Tue Jan 13 19:44:15 2004
*
* @author Adrienne Decker
* @version
*/
public class Triangle extends Figure{
private int _base;
private int _height;
public Triangle ()
{
System.out.println("Creating Triangle Class with no parameters.");
_base = 0;
_height = 0;
}
public Triangle(Triangle other)
{
System.out.println("Creating Triangle Class from another Triangle.");
_base = other._base;
_height = other._height;
}
public Triangle(int base, int height)
{
System.out.println("Creating Triangle Class given base and height.");
_base = base;
_height = height;
}
public void draw()
{
System.out.println("Calling Triangle's draw method.");
}
public void erase()
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
{
System.out.println("Calling Triangle's erase method.");
}
}// Triangle
/**
* Question5.java
*
*
* Created: Fri Jan 09 20:07:39 2004
*
* @author Adrienne Decker
* @version
*/
public class Question5
{
public static void main(String[] args)
{
Figure f1 = new Figure();
f1.draw();
f1.erase();
f1.center();
Triangle t1 = new Triangle();
t1.draw();
t1.erase();
t1.center();
Rectangle r1 = new Rectangle();
r1.draw();
r1.erase();
r1.center();
}
} // Question5
6.
/**
* Figure.java
*
*
* Created: Tue Jan 13 19:41:56 2004
*
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
* @author Adrienne Decker
* @version
*/
public class Figure
{
public Figure ()
{
}
public Figure(Figure figure)
{
}
public void erase()
{
for ( int i = 0; i < 15; i++) {
System.out.println();
} // end of for ()
}
public void draw()
{
}
public void center()
{
this.erase();
this.draw();
}
}// Figure
/**
* Rectangle.java
*
*
* Created: Tue Jan 13 19:48:48 2004
*
* @author Adrienne Decker
* @version
*/
public class Rectangle extends Figure
{
private int _width;
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
private int _height;
public Rectangle ()
{
_width = 0;
_height = 0;
}
public Rectangle(Rectangle other)
{
_width = other._width;
_height = other._height;
}
public Rectangle(int width, int height)
{
_width = width;
_height = height;
}
public void draw()
{
for ( int i = 0; i < _height; i++) {
for ( int j = 0; j < _width; j++) {
System.out.print("*");
} // end of for ()
System.out.println();
} // end of for ()
}
}// Rectangle
/**
* Triangle.java
*
*
* Created: Tue Jan 13 19:44:15 2004
*
* @author Adrienne Decker
* @version
*/
public class Triangle extends Figure{
private int _height;
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
public Triangle ()
{
_height = 0;
}
public Triangle(Triangle other)
{
super(other);
_height = other._height;
}
public Triangle(int height)
{
_height = height;
}
public void draw()
{
for ( int i = 1; i <= _height; i++ ) {
for ( int j = 0; j < i; j++) {
System.out.print("*");
} // end of for ()
System.out.println();
} // end of for ()
}
public void erase()
{
super.erase();
}
}// Triangle
/**
* Question6.java
*
*
* Created: Tue Jan 13 20:02:12 2004
*
* @author Adrienne Decker
* @version
*/
public class Question6
{
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
public static void main(String[] args)
{
Triangle t1 = new Triangle(5);
t1.center();
Rectangle r1 = new Rectangle(6, 8);
r1.center();
}
} // Question6
7.
/**
* MultiItemSale.java
*
*
* Created: Tue Jan 13 20:07:29 2004
*
* @author Adrienne Decker
* @version
*/
public class MultiItemSale
{
private Sale[] _sales;
private int _curr;
public MultiItemSale ()
{
_sales = new Sale[10];
_curr = 0;
}
public void insertSale(Sale insert)
{
if ( _curr > _sales.length) {
this.resize();
} // end of if ()
_sales[_curr] = insert;
_curr++;
}
public void resize()
{
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
int currSize = _sales.length;
currSize *= 2;
Sale[] newSales = new Sale[currSize];
for ( int i = 0; i < _curr; i++) {
newSales[i] = _sales[i];
} // end of for ()
_sales = newSales;
}
public Sale getSale(int index)
{
return _sales[index];
}
public double computeTotal()
{
double result = 0.0;
for ( int i = 0; i < _curr; i++ ) {
result = result + _sales[i].bill();
} // end of for ()
return result;
}
//Students should be encouraged to write an equals, and
// clone method for completeness
public String toString()
{
String result = "";
for ( int i = 0; i < _curr; i++) {
result += _sales[i] + "\n";
} // end of for ()
return result;
}
}// MultiItemSale
/**
* Question7.java
*
* Created: Fri Jan 09 20:07:48 2004
* Modified: Sat Mar 19 2005, Kenrick Mock
*
* @author Adrienne Decker
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
* @version 2
*/
import java.util.Scanner;
public class Question7
{
public static void main(String[] args)
{
MultiItemSale ms1 = new MultiItemSale();
Scanner keyboard = new Scanner(System.in);
while ( true )
{
System.out.println("Enter S for a sale, D for discounted " +
"sale or Q to quit");
String first = keyboard.nextLine();
if ( first.charAt(0) == 'Q' || first.charAt(0) == 'q') {
break;
} // end of if ()
else if ( first.charAt(0) == 'S' || first.charAt(0) == 's') {
System.out.println("Enter name of item: ");
String item = keyboard.nextLine();
if ( item == null ) {
System.err.println("Null string");
System.exit(1);
} // end of if ()
System.out.println("Enter item's price: ");
double temp = keyboard.nextDouble();
keyboard.nextLine(); // Eat newline
if ( temp < 0 ) {
System.err.println("Negative price.");
System.exit(1);
} // end of if ()
Sale s1 = new Sale(item, temp);
ms1.insertSale(s1);
} // end of if ()
else if ( first.charAt(0) == 'D' || first.charAt(0) == 'd' ) {
System.out.println("Enter name of item: ");
String item = keyboard.nextLine();
if ( item == null ) {
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.
Savitch, Absolute Java 2/e: Chapter 8, Instructor’s Manual
System.err.println("Null string");
System.exit(1);
} // end of if ()
System.out.println("Enter item's price: ");
double temp = keyboard.nextDouble();
keyboard.nextLine(); // Eat newline
if ( temp < 0 ) {
System.err.println("Negative price.");
System.exit(1);
} // end of if ()
System.out.println("Enter percentage discount as a double."
+ "\nFor example 6.5 for 6.5%");
double tempDis = keyboard.nextDouble();
keyboard.nextLine(); // Eat newline
if ( tempDis < 0 ) {
System.err.println("Negative discount.");
System.exit(1);
} // end of if ()
DiscountSale d1 = new DiscountSale(item, temp, tempDis);
ms1.insertSale(d1);
} // end of else
}
System.out.println("Total bill: $" + ms1.computeTotal());
}
} // Question7
Copyright © 2005 Pearson Education Addison-Wesley. All rights reserved.