CSCI 241 Labs: PreLab 10
Getting to the Point
Introduction
During lab this week you will develop a class to represent 2D points.
This document is meant to start you thinking
about the design of the Point
class.
As you should recall from high
school mathematics, two dimensional
points have an x
component and a y
component.
That's about it. There is no need to read any further.
The class could
be defined as:
public class Point
{
public double x;
public double y;
}
In the main
we can create Points
and access the x
and y
values
without any problems. For example,
public static void main (String [] args)
{
Point p = new Point();
p.x = 5.0;
p.y = 7.0;
System.out.println("(" + p.x + ", " + p.y + ")");
}
This all works, and there is nothing wrong with it, except that it is
not very object-oriented. This is exactly the way points are
implemented in languages like C and Pascal. Java, which is
object-oriented, should be able to do better.
Data Encapsulation
Java gives us the ability to hide and protect
data within the class. When we declare the x
and y
values to be private,
our class can control access to them.
In fact, we have no problem with other objects seeing the x
and y
values, we just don't want them to be able
to change them except through our explicit permission, with a method.
You can accomplish this goal by declaring each instance variable to be
private
and then writing accessor
methods to return their values.
To allow other objects to update the instance variable values, we
write mutator
methods.
Our class now becomes something like:
public class Point
{
private double x;
private double y;
// get the x value - similar code needed for y
public double getX ()
{
return x;
}
// set the y value - similar code needed for x
public void setY (double newValueForY)
{
y = newValueForY;
}
}
Question:
How should you modify the println
statement
in the main()
method above to work with the new class definition?
Constructing Points
Now there is another problem with our main program. The two lines:
p.x = 5.0;
p.y = 7.0;
will generate syntax errors, since x
and y
are no longer public.
We need a way to initialize
our points, i.e.,
to set the x
and y
values at the time the Point
is created.
This is exactly why Java includes constructors.
A constructor is a method that allows us to initialize an object's data
members at the time it is created.
The Point
class should have two constructors.
The default constructor
takes no arguments and sets the point to (0, 0). The second constructor
requires two arguments, the initial x
value and initial y
value.
The following lines inside the main program would create points using
each constructor.
Point p = new Point(); // creates Point (0,0) using default constructor
Point q = new Point (2.3, -7); // creates Point (2.3,7)
Question:
What should the constructors look like in the Point
class definition?
Other Point Methods
There are a number of other basic operations on points.
In Java each of these would be implemented as a public method.
- String
toString() converts the point
to a String for printing.
Look at the println
statement given in the sample main
method above. Every time we want
to print a point, we want it to appear as (x,
y) where the x and y values are
filled in. Our toString()
method should format the point for us.
The body of this method will be
return "(" + x + ", " + y + ")";
The println
becomes
System.out.println(p.toString());
Aside: While this is an advanced topic, it is worth noting that
Java is
actually smart enough to invoke the toString()
method automatically when printing.
The println()
could be written as:
System.out.println(p);
which would print the same result.
- double
distanceToOrigin() calculates
the distance from the point
to (0, 0). As you should recall from high school math, the distance
formula is:
- double
distanceTo(double px, double py)
calculates and returns the distance from the point to (px, py). As you
should recall from high school math, the
distance formula here is:
Questions:
- What will the code look
like in the main()
method that invokes each of the distance methods?
- The last method is an
instance method that takes two doubles as
parameters. Do you think it could be written to take a second Point as
a single parameter, instead?
Testing Point Methods
The Point class now has:
- Two private data members
- Two constructors
- Two accessor ("getter")
methods
- Two mutator ("setter")
methods
- A toString()
method
- Two distance methods
Seeing that the class compiles is not nearly enough to know that all
its
methods work correctly. We need to test each method thoroughly.
This is one of the real strengths of BlueJ. BlueJ lets us instantiate
objects and run their methods without writing any additional code.
The disadvantage of testing using BlueJ's object bar is that each test
must be run manually. In real world development situations, code is
tested and retested and retested.
Manual testing would be very inefficient.
Tests are typically run through a main program that is responsible for
nothing but testing.
To retest a program simply requires that you rerun the main.
Testing is not easy, either. To
guarantee that a method works, we should test it over several different
cases.
For example, the distanceTo(double
px, double py) should be tested
for several arbitrary points. It should also be tested with two points
that have the same x
value (vertical to each other). Likewise it should be tested for two
points that have the same y
value (horizontal to each other). Finally, what happens
if you ask for the distance from a point to itself?
Questions:
- How should we test the
constructors?
- What tests should be run on
the accessors and mutators?
- How many different test
cases can you think of for the distanceToOrigin()
method?
The Point of it All
There are many places where having a Point class is useful.
For example, two points determine a line.
Three nonlinear points give us a triangle.
More complex polygons just require more points.
In Computer Graphics, each pixel on the screen is treated as a point.
If we just consider triangles,
three of our Points determine the triangle.
Using methods from our Point class we can determine the perimeter of
the
triangle. Using our methods and the methods from the ACM graphics
library, we can draw the triangle to the screen.
In this week's lab you will get
a chance both to create a Point class and
exercise it in some interesting applications.