| 6.170 | Laboratory in Software Engineering
Spring 2000 Problem Set 4: Type Hierarchies Due: March 2, 2000 Handout 8 |
Each assignment should be handed in as hardcopy to your TA or to the course secretary (Kincade Dunn, NE43-529) by 4:30 PM on its due date. It is usually most convenient to give the assignment to your TA at the end of class on that day. Additionally, the source and compiled code for each problem set should be made available on Athena so your TA can test your program.
You should put your solution to this problem set in ~/6.170/ps4.
See the general information sheet (handout 1) for more detail

FigureThing provides an abstraction for objects that can be cloned and drawn in a window. The specification for FigureThing can be found in Appendix A. Each FigureThing object consists of a set of properties: location, color, shape, and size. However, merely drawing objects in a window is not very interesting. Therefore, you will extend FigureThing to AnimatedThing so that it supports the Animatible interface. The specifications for AnimatedThing and the Animatible interface can be found in Appendix B and Appendix C respectively. AnimatedThing objects differ from FigureThing objects in that the former have an additional property, namely velocity, and support the step method defined in the Animatible interface.
Both FigureThing and AnimatedThing are abstract classes. Therefore,
you cannot instantiate them. However, from AnimatedThing, there are
two levels of concrete subclasses, which can be instantiated. The
direct subclasses of AnimatedThing consist of RectangleThing and OvalThing.
The second level subclasses consist of SquareThing and CircleThing.
Since a square is also a rectangle, it is natural for SquareThing to be
implemented as a subclass of RectangleThing. The same holds true
between CircleThing and OvalThing.
A sample screen shot of the GUI program is shown on the left. The appearance of the window may vary slightly from one window environment to another window environment. The entry point for the program is defined in ps4.java. It creates a window and displays it on the screen. The features and behavior of the window are defined in MainFrame.java. The window contains a menu bar. Objects in the FigureThing hierarchy are created from the File|New menu of the window. Besides a menu bar, the window also contains a panel whose definition can be found in MainPanel.java. Objects created from the File|New menu are added to the panel and can be manipulated inside. Instructions about the use of the panel can be obtained from the Help|About dialog box.
When you implement the classes in the FigureThing hierarchy, you will come across objects of type Point, Dimension, Rectangle, Color, and Graphics. These are standard Java classes and their documentation can be found at http://www.javasoft.com/products/jdk/1.2/docs/api/index.html . The use of Point, Dimension, Rectangle, and Color are straight-forward. To draw on the screen, you have to manipulate a Graphics object.
In order to manage multiple windows that can overlap with each other and can be resized, moved, and iconized by users, most window environments do not allow applications to draw directly on the screen. Instead, each application draws on a graphics context provided by the window environment and the window environment maps the graphics context onto the screen. In Java, a graphics context is an object of type Graphics. (In the version of Java you are using, it is actually an object of type Graphics2D, which is derived from Graphics. But to maintain compatibility with older versions of Java, graphics contexts are still passed around as objects of type Graphics. Therefore, if you need to use a graphics context as a Graphics2D object, you need to down cast it from Graphics first.) You will need to draw on a graphics context when you implement the abstract method draw in FigureThing in its subclasses. The graphic context is passed to draw as its argument. To draw on it, all you need to do is to call some methods defined in Graphics or Graphics2D on it. Examples on manipulating graphics contexts can be found in Chapter 14 of the Beginning Java 2 book.
In general, when writing a GUI application, you will have to deal with multiple coordinate systems. This is explained in Chapter 14 of the Beginning Java 2 book as well. However, in this problem set, you will be drawing inside the MainPanel only. Therefore, you will only deal with the coordinate system of the panel. The origin of the panel is located at its upper left corner. The positive x axis runs from left to right and the positive y axis runs from top to bottom. All the coordinates you are going to work with are expressed in this coordinate system.
If you look at the specification of FigureThing, you will notice that the term "bounding rectangle" appears in several places. The bounding rectangle of a figure is the smallest rectangle that aligns with the current coordinate system and completely encloses the figure. In this problem set, you are only expected to draw figures aligned with the coordinate system of MainPanel, i.e. you do not need to draw slanted figures. Therefore, the bounding rectangles of your rectangles and squares will be the same as the rectangles and the squares themselves. Those of your ovals and circles are illustrated below.

After you have finished the implementation of AnimatedThing, you can
try compile the GUI program to see if you have made any compile-time errors
in AnimatedThing. Here are the steps to do so:
|
To execute your implementation:
|
Problem 3: Extending RectangleThing and OvalThing
In this problem you will extend RectangleThing and OvalThing to produce SquareThing and CircleThing. Partial definitions of SquareThing and CircleThing can be found in SquareThing.java and CircleThing.java.
Problem 4: Testing
The GUI program provided is not a complete test of your code. In this problem you will carry out black-box testing on the classes that you have implemented. You are advised to read Program Development in Java: Abstraction, Specification, and Object-Oriented Design Section 10.4 and 10.6 before you attempt this problem. Also, when you submit your test cases and results, remember to provide clear documentation as to which constructor(s) and/or method(s) you are testing in each case and provide justification for each of your test cases.
public FigureThing()
// effects: Initializes this with
a random color
//
such that its location is (0, 0).
public abstract void draw(Graphics g);
// effects: draws this onto g
public abstract boolean hitTest(Point
pt);
// effects: returns true if the
point pt lies inside the bounding rectangle
//
of this. Returns false otherwise.
public abstract Rectangle getBounds();
// effects: returns the bounding
rectangle of this.
public abstract void setSize(int width,
int height) throws ImpossibleSizeException;
// modifies: this
// effects: Resizes this so that
its bounding rectangle has width
//
<width> and height <height>,
//
unless this cannot be resized to the specified dimension
//
=> no modifications to this, throw ImpossibleSizeException.
//
(the exception suggests an alternative dimension
//
that is supported by this)
public Object clone() throws CloneNotSupportedException
// effects: standard clone operator
public Point getLocation()
// effects: returns the top left
corner of the
//
bounding rectangle of this.
public void setLocation(Point pt)
// modifies: this
// effects: moves this to pt, i.e.
this.getLocation()
//
returns pt after call has completed.
public Color getColor()
// effects: returns this's color
public void setColor(Color c)
// modifies: this
// effects: sets this's color to
be c
}
Appendix B: AnimatedThing Specification
abstract class AnimatedThing extends FigureThing implements
Animatible
{
// Overviews: An AnimatedThing is a FigureThing
with an additional property:
//
velocity. Thus, a typical AnimatedThing is
//
{location, color, shape, size, velocity}
//
AnimatedThing()
// effects: Initializes an AnimatedThing
object in a similar way to
//
initializing a FigureThing object. Each of the horizontal
//
and vertical velocities of the new object is set to a random
//
integral value i s.t. -3 <= i <= 3 and i != 0
public void setVelocity(int vx, int vy)
// modifies: this
// effects: Sets the horizontal
velocity of this to vx and
//
the vertical velocity of this to vy.
public int getHVelocity()
// effects: Returns the horizontal
velocity of this.
public int getVVelocity()
// effects: Returns the vertical
velocity of this.
public void step(Dimension bound)
// modifies: this
// effects: Let p = location
//
v = (vx, vy) = velocity
//
r = the bounding rectangle of this
//
Set p_post = p + v
//
unless doing so will bring part of r outside bound
//
=> If the horizontal component of the attempted motion
//
of r is away from the center of bound,
//
set vx_post = -vx
//
And if the vertical component of the attempted motion
//
of r is away from the center of bound,
//
set vy_post = -vy
//
Set p_post = p
public Object clone() throws CloneNotSupportedException
// effects: standard clone operator
}
Appendix C: Animatible Interface
interface Animatible
{
// Overviews: Animatibles are objects
that can be animated.
//
Animation is achieved by invoking a number of steps
//
of small modifications, movements, or transformations
//
on this.
public void step(Dimension bound);
// modifies: this
// effects: Updates the state of
this to the appropriate value for
//
the next animation step. The argument bound indicates
//
the dimension of the area within which this is allowed
//
to move.
}