INFORMATION & COMPUTER SCIENCE DEPARTMENT, KFUPM
ICS201, SECTIONS 02 (002
Semester)
INTRODUCTION TO COMPUTER SCIENCE
LAB #01 Further Object-Oriented Concepts
Instructor: Bashir M. Ghandi
To gain experience with:
Inheritance is an important object-oriented concept that allows classes
to be reused in order to define similar, but distinct, classes. It also provides a mechanism for creating
generalized solutions through polymorphism.
In this lab we walk through the development of a class hierarchy and a
program that makes use of several classes in the hierarchy.
We begin by looking at three files which make up the
inheritance hierarchy all of them in the cs.graphics package.
Shape
/ \
/ \
Line
Rectangle
Shape.java
This is the parent class. It is not very useful as it stands, but it soon
will be, even though we will not modify it directly at all. Note the
overloaded constructors, and the draw method that has no code in its
definition.
package cs.graphics; import java.awt.*; /** Represents a generic shape, having a particular color. */ public class Shape { protected Color color; /** Defaults the color to black. */ public Shape () { this.color = Color.black; } // constructor Shape /** Specifies the color. */ public Shape (Color color) { this.color = color; } // constructor Shape /** Draws the shape. */ public void draw (Graphics g) { } // method draw } // class Shape |
Line.java
The first child of
Shape is Line. Note that this class extends the Shape class. Both
classes have a draw method.
package cs.graphics; import java.awt.*; import java.awt.geom.*; /** Represents a line of specific size and color, drawn at a
particular location. */ public class Line extends
Shape { private int x1, y1, x2, y2; /** Specifies starting and ending points, uses defaults color. */ public Line (int x1, int y1, int x2, int y2) { super(); this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2; } // constructor Line /** Specifies starting and ending points, and color. */ public Line (Color color, int x1, int y1, int x2, int y2) { super(color); this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2; } // constructor Line /** Draws the line. */ public void draw (Graphics g) { Graphics2D g2 = (Graphics2D) g; g2.setColor (color); g2.draw (new Line2D.Double(x1, y1, x2, y2)); } // method draw } // class Line |
Review questions:
What
is it called when two methods/constructors have the same name in a single
class?
What
is it called when a parent and child have methods with the same name and
signature?
True/False:
Because Line is a child of Shape, Line objects will be able to do everything
that Shape objects can do and more.
Why
was the color field in the Shape class declared as protected? What else could we use instead and what will
be the effect?
Rectangle.java
This
class is also derived from the Shape class. It not only has color and
starting coordinates, but also height and width. Note the similarities between
the Rectangle class and the Line class.
package cs.graphics; import java.awt.*; /** Represents a rectangle of specific size and color, drawn in a particular location. */ public class Rectangle
extends Shape { protected int x, y; protected int width, height; /** Specifies location and size, uses defaults color. */ public Rectangle (int x, int y, int width, int height) { super(); this.x = x; this.y = y; this.width = width; this.height = height; } // constructor
Rectangle /** Specifies location and size, and color. */ public Rectangle (Color color, int x, int y, int width, int
height) { super(color); this.x = x; this.y = y; this.width = width; this.height = height; } // constructor
Rectangle /** Draws the rectangle. */ public void draw (Graphics g) { Graphics2D g2 = (Graphics2D) g; g2.setColor (color); g2.draw(new java.awt.Rectangle(x, y, width, height)); } // method draw } // class Rectangle |
Review questions:
Why
do we have to use the full name, java.awt.Rectangle, in creating the rectangle object in the draw
method above?
What
happens if we omit the call to super in the first constructor of the Rectangle
class?
What
if the Shape class has only the second (not the default) constructor?
The following two classes,
which could be stored in a single file RandomDraw.java in the cs.labs.lab01 package, make use of the family of classes discussed
above to implement an applet that draws random shapes.
Trace the code and make
sure you understand everything about it.
package cs.labs.lab01; import
cs.graphics.*; import java.applet.Applet; import java.awt.Graphics; import java.awt.Color; import java.util.Random; /** This applet creates and draws multiple random shapes. */ public class RandomDraw
extends Applet { final int MAX_SHAPE = 20; Shape[] shapes = new
Shape[MAX_SHAPE]; ShapeCreator creator; /** Creates and stores multiple shapes. */ public void init() { shapes = new Shape[MAX_SHAPE]; creator = new ShapeCreator(); for (int index = 0; index < MAX_SHAPE; index++) { shapes[index] = creator.newShape(); } } // method init /** Draws all of the shapes on the applet. */ public void paint (Graphics g) { for (int index = 0; index < MAX_SHAPE; index++) { shapes[index].draw (g); } } // method paint } // class RandomDraw /** The ShapeCreator class contains code to create random shapes, each with random size, color, and location. */ class ShapeCreator { final int DIMENSION_MAX = 300; //maximum value of a dimension final int NUM_SHAPES = 2;
//different possible shapes(line & rectangle) final int LINE = 1; //label for Line shape final int RECTANGLE = 2;
//label for Rectangle shape Random rand = new Random(); /** Returns a random integer between 1 and max. */ public int randomInt (int max) { return Math.abs(rand.nextInt()) % max + 1; } // method randomInt /** Returns a random color created using random RGB values */ public Color randomColor() { return new Color
(rand.nextFloat(),rand.nextFloat(),rand.nextFloat()); } // method
randomColor /** Returns a random shape with random characteristics. */ public Shape newShape() { Shape result; int x1, y1, x2, y2, x, y, width, height; switch (randomInt(NUM_SHAPES)) { case LINE: x1 = randomInt (DIMENSION_MAX); y1 = randomInt (DIMENSION_MAX); x2 = randomInt (DIMENSION_MAX); y2 = randomInt (DIMENSION_MAX); result = new
Line (randomColor(), x1, y1, x2, y2); break; case RECTANGLE: default: x = randomInt (DIMENSION_MAX); y = randomInt (DIMENSION_MAX); width = randomInt (DIMENSION_MAX); height =
randomInt (DIMENSION_MAX); result = new Rectangle (randomColor(), x, y, width,
height); break; } return result; } // method newShape } // class ShapeCreator |
Review questions:
The variable shapes is defined as an array of Shape objects (Shape[]).
Yet what the ShapeCreator object stores into it are objects of class Line and
Rectangle. How is this possible?
The paint method in the
RandomDraw class calls the draw
method of each object stored in the array. How is it that the correct shape is
drawn even though the name of the method does not change. What do we call this feature?
We saw in the last lab that to execute an application that makes use of
user-defined packages, we specify the location of the package using the
classpath option:
java –classpath “z://”
cs.labs.lab00.TestPoint
Where the base package (cs) is in the root of the z dribe.
We pass similar parameter to JCreator to achieve the same result.
The problem now is how do we supply the classpath for applets? -- recall applets are executed by loading
their class file in an HTML file.
For applets, we specify the classpath for user-defined
packages by using the codebase option of the APPLET
tag in the HTML file.
The codebase specifies the
location of the base package relative to the HTML file. For example, if the HTML file is stored on
the root of z drive, which is also where the base package (cs) is stored, then
the following code should be used:
<APPLET codebase="." code=cs.labs.lab01.RandomDraw.class width=500
height=500> </APPLET> |
Notice that “.” means the
current foldert (the folder containing the html file). Thus, the command says, start looking for
the cs package from the current folder.
If however, the HTML file is in the lab01 folder,
then we need to use . . to point back to the
root folder as follows:
<APPLET codebase="../../../" code=cs.labs.lab01.RandomDraw.class width=500
height=500> </APPLET> |
Open the file “RandomDraw.html” containing the above
code from the lab01 folder and execute it to test the applet.
If the user-defined package is in a JAR file, we use
the ARCHIVE option of the APPLET tag to specify the JAR file.
For example, if both the JAR file and the HTML file
are in the same folder, we use the following:
<APPLET ARCHIVE = “cs.jar” codebase="." code=cs.labs.lab01.RandomDraw.class width=500
height=500> </APPLET> |
In last lab, we learnt how to create Java documentation from a single
source file.
We can create Java documentation for multiple packages by specifying the
individual packages with the javadoc command. For example, the following creates java
documentation for all the packages we created so far:
javadoc –classpath “z://” cs.graphics cs.utilities
cs.databases cs.labs.lab00 cs.labs.lab01
If the packages get too many, we can store them in a text file one
package per line and execute the following form of the command:
javadoc –classpath “z://” @filename
where filename is the file containing the list of packages.
By default, the javadoc stores the HTML files it generates in the same
folder containing the classes. We can
make it to store the files in another folder using the –d option.
For example, to store the HTML in a folder z://docs we use the following:
javadoc –d “z://docs” –classpath “z://” cs.graphics
cs.utilities cs.databases cs.labs.lab00 cs.labs.lab01
or
javadoc –d “z://docs” –classpath “z://” @filename
1. Execute the HTML file of the RandomShape applet
a few times and observe the output.
Generate the documentation for all the packages in a folder “docs”
under your z drive.
2.
(a) In a file called Ellipse.java, create
a class called Ellipse derived from the Rectangle class. You will observe that you do not need any
additional variable in this case and the constructors only need to call the
super constructor. However, you need to
override the draw method.
(b) In a file called Square.java, create a
class called Square derived from the Rectangle class. The Square constructors should only accept
one width dimension, since a square’s height and width are the same. Pass the
width along to the parent’s constructor through a super call as both the height
and width of the rectangle. Because the draw method of the Rectangle is
sufficient for the square, there is no reason to override it this time.
(c) Modify the CreateShape accordingly and
compile and execute the applet.
3.
In the cs.databases
package, write a class Worker and two subclasses, HourlyWorker
and SalariedWorker. Every worker
has a name and salary rate.
Write a method computePay(int hours) that computes the weekly pay
for every worker. An hourly worker is
paid according to the salary rate if the number of hours he worked is not more
than 40. However, every if he works
more than 40 hours, the excess hours are paid at a rate of 1.5 times the normal
rate. The salaried worker is paid for
40 hours no matter the actual number of hours worked. Write a static method that uses polymorphism to compute the pay
of any Worker. Supply a test program
that tests these classes and methods.