Aquarium Lab Series
Reading Specifications and Writing Client Code
This set of Mini-Lab Exercises is the first in a series in which students build a small program with several fish moving around in an aquarium. The set includes the following exercises:
Each section contains an Introduction to a problem or task, (usually) abridged versions of one or more Patterns that will be useful in solving the problem or completing the task, and an Exercise.
Before working through this Mini-Lab, students should understand the role
of the main method in an application, the role of classes and objects,
and the syntax for documenting code with comments. Students should also have
read over the patterns that appear in this document before the lab.
AquaSimApplication class. There is also
an Aquarium class and an AquaFish class. The skeleton
program constructs an Aquarium object in the main method;
in the exercises that follow, you will be creating several AquaFish
objects in the aquarium and directing them to move.
The program also contains an AquaSimGUI class that provides a
graphical user interface for the Aquarium Lab Series. The interface is
an area where the program can display a graphical
picture of an aquarium and its fish. The program also includes several "black
box" utility classes that provide necessary functionality for the AquaFish
and AquaSimGUI classes, but which you will not need to read or
modify as part of this lab series.
Exercise
|
main method in AquaSimApplication.java
creates an aquarium, but it doesn't have any fish in it. We can use
the Declare-Construct-Initialize pattern to create
fish to go
in the aquarium. The AquaFish interface gives the
specifics on how to construct objects of the class.
Therefore, you should specify the type of the new variable (declare), set aside space for it in memory (construct), and (usually) initialize it to a meaningful value before you use it in your program. Give the variable an Intention Revealing Name to make your code easier to read, understand, and maintain. If the variable is an object of a class, Read the Interface for Constructors to determine how to construct and initialize the variable. You may not need to explicitly initialize the variable if it will automatically be given an appropriate default value or if you always set it in your algorithm before trying to use it.
A variable associated with a class object in Java is actually a reference to the actual object. Creating the variable and associating it with an object are two separate steps. The variable declaration declares the type of object the variable will refer to, and initializes it by default to be a null reference, as in the example below.
MyClass newObject; // constructs reference
The variable can be assigned to refer to an existing object, or to an explicitly
constructed object. A newly constructed object is initialized by a constructor method,
and it is often possible to pass parameters to a constructor
to affect the initialization. In Java, empty parentheses are used when invoking
the default constructor. For any given class, Read the Interface
for Constructors to determine how to construct and initialize objects of
the class.
MyClass newObject = oldObject; // constructs new reference to existing object
MyClass newObject = new MyClass(); // constructs using default constructor; assigns to reference
MyClass newObject = new MyClass(initValue); // constructs using one-parameter constructor; assigns to reference
It is also possible to construct both a reference and the new object to which
it refers in a single line of code.
MyClass myObj = new MyClass(initValue); // constructs and initializes both reference and new MyClass object
In Java, a variable definition of a primitive type declares the type of an object and sets aside the memory for it (constructs it) simultaneously. It is also possible to initialize a variable of a primitive type at the same time.
int i; // constructs an integer (and initializes to 0)
int j = 0; // constructs an integer, initializing to 0
Therefore, all of the names in your programs (variables and parameters, classes, methods) should denote the purpose of the item they refer to. Variables, for example, should be named for the objects they represent.
The Intention Revealing Name pattern is described more fully in Bergin's Coding at the Lowest Level: Coding Patterns for Java Beginners. The pattern comes from Kent Beck's Smalltalk Best Practice Patterns (Prentice Hall, 1997).
Therefore, read the constructor specification(s) in the class interface to determine how to construct, and initialize if necessary, the object that you need. Concentrate on the constructors that are accessible to you; for example, if you are writing client code, read the public constructor specifications.
A constructor specification will tell you
Reading a constructor or method specification and then writing code that meets the specification is tricky, especially for novices. This is because the client code you write will not look exactly like the specification. Think of the specification as being like a dictionary entry. Imagine that you want to use the word "cat" in a sentence, but you're not sure of its meaning. You look it up in a dictionary and find the following.
Let's look at an example from the Aquarium class. In this class, there is a single constructor. How do we know? A constructor specification looks like a method whose name is the same as the class. There is only one "method" called Aquarium in the class interface.
This specification tells us that the constructor is public, so we may use it in our client code, and that it requires two integer parameters. When we construct an Aquarium object we do not need to specify that it is public nor what the types of its parameters are, anymore than we have to specify that a cat is a noun when we use it in a sentence. We do, however, need to provide values for the two parameters. Thus, we could construct a 600 x 400 Aquarium as follows:public Aquarium(int width, int height)Construct an Aquarium with user-specified size. Parameters:width- width of the aquarium when displayed (in pixels)height- height of the aquarium when displayed (in pixels)
Aquarium myAquarium = new Aquarium(600, 400);
What if the Aquarium class also included a second constructor that took no parameters?
public Aquarium()
Construct an Aquarium with default size.
In this case, we could use either constructor. We could construct an Aquarium
with the default size (whatever that may be), with the following:
Aquarium myAquarium = new Aquarium();
Exercise
|
Therefore, read the method specifications in the class interface to determine how to invoke methods on the object (also known as "sending a message" to the object).
A method specification will tell you
Let's look at two examples from the Aquarium class: width and
validLoc.
public int width()
Determine the width of the aquarium.
Returns: the width of the aquarium
What can we learn from these declarations? Both methods are public, so we may use them in client code. Both have return values (public boolean validLoc(int xCoord, int yCoord)Determine whether the given coordinates specify a valid location. Parameters:xCoord- x coordinate of location to be checkedyCoord- y coordinate of location to be checked Returns:trueif specified location is within aquarium
width returns
an integer value; validLoc returns a boolean value), so we should
capture the value returned in a variable or embed the method call in a larger
expression. The width method does not take any parameters and returns
an int. The validLoc method requires two parameters
and returns a boolean value. Thus, this method may be used in a logical expression.
How can we use this knowledge? If y is a well-defined integer
value (see the Declare-Construct-Initialize pattern), then
the following are valid examples of these two methods.
int aquariumWidth = myAquarium.width();
if ( myAquarium.validLoc(aquariumWidth / 2, y) )
// do something with this valid location ...
As with constructors, you do not need to specify the type of the parameters
as you pass them (see the Read the Interface for Constructors
pattern). Nor do you specify the return type of the method as you call it.
A method with a void return type does not return any value
to the method that called it. Instead, it usually modifies its object, produces
output, or changes the state of the program in some other way. It may or may
not require parameters. Here is a specification of a void method
from the Display class.
public void showAquarium()
Display only the Aquarium: paint the aquarium blue to cover up old fish.
Since showAquarium does not return anything, it cannot be embedded
in an expression or an assignment statement. A void method is a
statement on its own. For example,
userInterface.showAquarium();
Exercise
|