Note: I
will post solutions for problems 1-8 tonight. I think you'd benefit from
trying to solve them, and when I post the solutions you could check your
solutions against those posted.
What comes next is:
A201/A597
LAB ASSIGNMENT EIGHT
9. This problem has several parts:
- Write a simple
Vehicle class that has fields for
(at least) current speed, current direction in degrees, and owner
name.
- Add a static field to your
Vehicle class for the
highest Vehicle Identification Number issued, and a non-static
field that holds each vehicle's ID number.
- Write a
main method for your Vehicle class that
creates a few vehicles and prints out their field values. Note that
you can also write a separate tester program as well.
- Add two constructors to
Vehicle. A no-arg constructor
and one that takes an initial owner's name. Modify the tester program from
the previous step and test your design.
- Make the fields in your
Vehicle class private,
and add accessor methods for the fields. Which fields should have methods to
change them and which should not?
- Add a
changeSpeed method that changes the current speed
of the vehicle to a passed-in value, and a stop method that
sets the speed to zero.
- Add two
turn methods to Vehicle. One that
takes a number of degrees to turn, and one that takes simply either a
Vehicle.TURN_LEFT or a Vehicle.TURN_RIGHT
constant. Define the two constants accordingly.
- Add a static method to
Vehicle that returns the highest
identification number used so far.
- Add a
toString method to Vehicle.
This problem is really following the steps developed in the
Dilbert lecture so if you understand that lecture you will have
no problem putting together the solution to this lab assignment.
This is the end of LAB ASSIGNMENT EIGHT.
(Only Vehicle needs to be turned in).
I also include here the text for the Fractions exercise
that appears in the lecture notes of yesterday.
10. Define a class of Fractions
Here's how we started in class:
class Fraction {
int num;
int den;
Fraction(int a, int b) { this.num = a; this.den = b;
}
public String toString() {
return " (" + num + "/" + den + ") ";
}
Fraction add(Fraction other) {
return new Fraction(
this.num * other.den + this.den * other.num,
this.den * other.den
);
}
public static void main(String[] args) {
Fraction a = new Fraction(1, 3);
Fraction b = new Fraction(2, 3);
System.out.println(a.toString());
System.out.println(b);
System.out.println(a.add(b));
}
}
Consider ordinary fractions like 3/4 and
-1/2. A fraction is the ratio of two integers:
a numerator and a denominator. Create a user-defined type for fractions
by defining a class Fraction. The class should supply a set
of necessary operations on fractions
- addition
- subtraction
- multiplication
- division
and should hide implementation details of data representation and
internal manipulations.
Remember that a class encapsulates data structures with access and
manipulation procedures. In designing a class, an important task is to
decide on the internal data representation which is isolated from the
outside view. Member methods will keep the data representation consistent.
Outside methods are not allowed to create or modify the internal structures
directly. They may do this by calling methods in the class.
Here are some (internal) representation considerations to guide your design:
- A fraction is essentially a pair of integers called
numerator and denominator.
- The numerator carries the sign of the fraction and can be
positive, negative, or zero.
- The denominator is kept positive and can never be zero.
- Fractions with the same value may have different representations
(for example 1/2, 2/4,
3/6). In our representation let's decide for
equal fractions to have the same numerator and the same denominator.
That means that all fractions must be reduced to their lowest terms.
(A data representation in which all equal quantities are represented
uniquely is known as a canonical representation. Keeping
fractions canonical is desirable and we should enforce this.)
The canonical representation of 0 (zero) as a fraction is
0/1.
Your Fraction class can be designed to enforce such conventions,
not just to have them as principles that one can choose to follow or ignore.
This is one big advantage of object-oriented programming. The canonical
representation conventions should be enforced by the Fraction
constructor.
The constructor should take the two arguments n and
d and construct a fraction n/d
out of it. The denominator of the resulting Fraction should not
be zero or negative. The fraction should be reduced by removing the
gcd (greatest common divisor) between the numerator and
the denominator. You should define a member method gcd
that computes the gratest common divisor of two numbers and make the
constructor use it to create canonical Fractions.
gcd should be implemented as a classwide method since
it is independent of Fraction instances. It should be
declared private because it does not contribute to the
public interface of the Fraction class.
We provided gcd in a separate class, Euclid.
The operations for fractions listed above should implement binary operations.
In other words we are going to define methods such that a Fraction
can be added to, subtracted from, multiplied with, or divided by another
Fraction. The result should be a Fraction.
You should also define a few predicates.
Each Fraction that you create should be able to respond to the
following questions:
-
isZero()
-
isInt()
-
equals(anotherFraction)
-
greaterThan(anotherFraction)
You should also add a toString method to Fraction
(an instance method) that returns a String representation of a
Fraction. It must be an instance method as it is used to produce
a representation of the object in a textual context.
Testing your Fractions:
// TestFrac.java
class TestFrac {
public static void main(String[] args) {
Fraction x = new Fraction( 1, 20);
Fraction u = new Fraction(-1, 60);
Fraction v = new Fraction( 1, 30);
Fraction y;
y = x.plus(u).minus(v); // in one step!
System.out.println( x + " + " +
u + " - " +
v + " = " + y);
}
}
Last updated: Jul 11, 2001 by Adrian German for A201