  Second Summer 2002

An Older Set of Notes for Lab Ten: Classes and objects revisited. Solutions.
Here are the answers to all the problems.

The answers (or, rather, the hints) are in blue.

Warm-ups:

1. Consider the following 'nonsense class'.

```class A
{ public A() { n = 0; } // constructor
public A(int a) { n = a; } // constructor
public void f() { n++; } // mutates n
public void g() { f(); n = 2 * n; f(); }
// g mutates n directly and indirectly (f)
public int h() { return n; } // accessor of n
public void k() { System.out.println(n); }
// does not return, only prints, the value of n
private int n; // instance variable
}```
Identify the constructors, mutator functions, and accessor functions. What kind of variable is `n`?

2. With the nonsense class from the preceding exercise, determine what the following program prints.

It prints `9` and `17` and here's why:

```public static void main(String[] args) {
A a = new A(); // a.n is 0
A b = new A(2); // b.n is 2
A c = b; // c points where b points so c.n = b.n = 2
A d = new A(3); // d.n is 3
a.f(); // a.n is 1
b.g(); // b.n becomes 3, 6, then 7
c.f(); // c.n is b.n and it becomes 8
d.g(); // d.n becomes 4, 8, then 9
d.k(); // d.n is printed on a line by itself
A e = new A(a.h() // a.n is 1
+ b.h() // b.n is 8 and is equal to c.n
+ c.h() // which is 8
); // so e.n is set to 1 + 8 + 8 = 17
e.k(); // e.n (17) is printed on a line by itself
}```
Work through the program by hand. Do not actually compile and run the program. Then run it and compare the results.

3. Implement all the methods of the following class:

```class Person {
public Person() {
name = "YetToBeNamed";
birthdayYear = 1999; // my default
}
public Person(String givenName, int yearOfBirth) {
name = givenName;
birthdayYear = yearOfBirth;
}
public String getName() {
return name;
}
public String changeName(String name) {
String aux;
aux = this.name;
this.name = name;
return aux;
}
public int getAgeInYears(int currentYear) {
return currentYear - birthdayYear;
}
private String name;
private int birthdayYear;
public static void main(String[] args) {
Person a = new Person();
Person b = new Person("Richard P. Feynman", 1918);
String name = a.changeName("The Next Richard Feynman");
System.out.println(
"Physicist " + name + " makes big " +
"discovery, touted as " + a.getName()
);
System.out.println(
b.getName() + " was " +
b.getAgeInYears(1945) +
" in 1945, in May. "
);
}
}```
Write a small test program that creates and works with objects of class `Person` as well.

As shown, the test program can be the very `main` method of the class we wrote.

Design exercises:

4. Implement a class `Address`. An address has

• a house number,
• a street,
• an optional apartment number,
• a city,
• a state and a
• postal code.
Supply two constructors:
• one with an apartment number
• and one without.
Supply a `print` function that prints the address with the street on one line and the city, state, and postal code on the next line.

Supply a method `compareTo` that tests whether one address comes before another when the addresses are compared by postal code.

```class Address {
int    houseNumber;
String street;
int    apartmentNumber;
String city;
String state;
String zipCode; // e.g., "47405-1234"
String street,
// no apartmentNumber
String city,
String state,
String zipCode) {
this.houseNumber = houseNumber;
this.street = street;
this.city = city;
this.state = state;
this.zipCode = zipCode;
}
String street,
int apartmentNumber,
String city,
String state,
String zipCode) {
this(houseNumber, street, city, state, zipCode);
this.apartmentNumber = apartmentNumber;
}
void print() {
System.out.println("Street: "      + street);
System.out.println("City: "        + city
+ "State: "       + state
+ "Postal Code: " + zipCode);
}
// same conventions as for Strings
return this.zipCode.compareTo(a.zipCode);
}
}```

5. Implement a class `Account`. An account has

• a `balance`,
• functions to `add`
• and `withdraw` money,
• and a function to `inquire` the current balance.
Pass a value into a constructor to set an initial balance.

If no value is passed the initial balance should be set to `\$0`.

Charge a `\$5` penalty if an attempt is made to withdraw more money than available in the account.

Enhance the `Account` class to compute `interest` on the current balance.

```class Account {
double balance;
balance += sum;
return sum;
}
double withdraw(double sum) {
if (sum > balance) {
balance -= 5;
return -5; // this will come in handy in Prob. 6
} else {
balance -= sum;
return balance; // Notice: always >= 0 (never < 0)
}
}
double inquire() { return balance; }
Account() { balance = 0; }
Account(double sum) { balance = sum; }
double interest (double rate) {
return rate * balance;
}
}```

6. Implement a class `Bank`. This bank has two objects

• `checking`
• and `savings`
of the type `Account` that was developed in the preceding exercise.

Implement four instance methods:

```deposit(double amount, String account)

withdraw(double amount, String account)

transfer(double amount, String account)

printBalances()
```
Here the account string is `"S"` or `"C"`. For the deposit or withdrawal, it indicates which account is affected. For a transfer it indicates the account from which the money is taken; the money is automatically transferred to the other account.

```class Bank {
Account checking;
Account savings;
void deposit(double amount, String account) {
else // my default
}
void withdraw(double amount, String account) {
if (account.equals("C")) checking.withdraw(amount);
else // my default
savings.withdraw(amount);
}
void transfer (double amount, String account) {
if (account.equals("C"))
if (checking.withdraw(amount) >= 0)
else // default
if (savings.withdraw(amount) >= 0)
else savings.add(5);  // no penalty for transfers
}
void printBalances() {
System.out.println(
"Checking: " + checking.inquire() +
"\nSavings: " + savings.inquire()
);
}
}```

7. Define a class `Country` that stores the name of the country, its population, and its area.

```class Country {
String name;
long population;
double area;
Country(String name, long population, double area) {
this.name = name;
this.population = population;
this.area = area;
}
}```

8. Write a class called `Triangle` that can be used to represent a triangle. It should include the following methods that return `boolean` values indicating if the particular property holds:

• `isRight` (a right triangle)
• `isScalene` (no two sides are the same length)
• `isIsosceles` (exactly two sides are the same length)
• `isEquilateral` (all three sides are the same length)
Write a simple tester program that creates a few triangles and asks them about their type.
```class Triangle {
int sideA, sideB, sideC;

Triangle (int a, int b, int c) { // constructor
sideA = a; sideB = b; sideC = c;
} // negative numbers and zero lengths accepted
// but see how isTriangle() used below

boolean isTriangle () {
int max = Math.max(Math.max(sideA, sideB), sideC);
return sideA > 0 && sideB > 0 && sideC > 0 &&
(max < sideA + sideB + sideC - max);
}
boolean isRight() {
int max = Math.max(Math.max(sideA, sideB), sideC);
return isTriangle() &&
(max * max) == (sideA * sideA) +
(sideB * sideB) +
(sideC * sideC) -
(max * max);
}
boolean isScalene() {
return isTriangle() &&
! isIsosceles(); // we get some peer help
}
boolean isIsosceles() {
return isTriangle() &&
(sideA == sideB ||
sideA == sideC ||
sideB == sideC);
}
boolean isEquilateral() {
return isTriangle() &&
(sideA == sideB && sideA == sideC);
}
public static void main(String[] args) {
Triangle a, b, c;
a = new Triangle( 3,  4,  5);
b = new Triangle( 0,  0, -1);
c = new Triangle( 6,  6,  6);
System.out.println(
a + " isosceles? Answer: " + a.isIsosceles()
);
System.out.println(
a + " right? Answer: "     + a.isRight()
);
System.out.println(
c + " isosceles? Answer: " + c.isIsosceles()
);
System.out.println(
c + " scalene? Answer: "   + c.isScalene()
);
}
String toString() {
System.out.println(
"Triangle: (" + sideA + ", "
+ sideB + ", "
+ sideC +
") ";
);
}
}```

9. For this problem what's listed below is just to get started.

This problem has several parts:

1. Write a simple `Vehicle` class that has fields for (at least) current speed, current direction in degrees, and owner name.

```class Vehicle {
int currentSpeed;
int currentDirection;
String owner;
}```
2. 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.

```class Vehicle {
int currentSpeed;
int currentDirection;
String owner;
static int highestVIN;
int VIN;
}```
3. 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.

```class Vehicle {

int currentSpeed;
int currentDirection;
String owner;
static int highestVIN;
int VIN;

public static void main(String[] args) {

Vehicle a = new Vehicle();
a.VIN = highestVIN++;
a.owner = "Larry Bird";

Vehicle b = new Vehicle();
b.VIN = highestVIN++;
b.owner = "Mark Jackson";

System.out.println("VIN: " + a.VIN + " belongs to " + a.owner);

System.out.println("VIN: " + b.VIN + " belongs to " + b.owner);

// Note that both cars are stopped, and facing East.

}
}```
4. 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.

```class Vehicle {
int currentSpeed;
int currentDirection;
String owner;
static int highestVIN;
int VIN;

Vehicle() { VIN = highestVIN++; }
Vehicle (String owner) { this(); this.owner = owner; }

public static void main(String[] args) {

Vehicle a = new Vehicle("Larry Bird");
Vehicle b = new Vehicle("Mark Jackson");

System.out.println("VIN: " + a.VIN + " belongs to " + a.owner);
System.out.println("VIN: " + b.VIN + " belongs to " + b.owner);
}
}```
5. 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?

```class Vehicle {
private int currentSpeed;
int getSpeed() {
return currentSpeed;
}
void changeSpeed(int newSpeed) {
currentSpeed = newSpeed;
}
private int currentDirection;
int getCurrentDirection() {
return currentDirection;
}
void setDirection(int newDirection) {
currentDirection = newDirection % 360;
}
private String owner;
int getOwner() {
return owner;
}
void setOwner(String newOwner) {
owner = newOwner;
}
private static int highestVIN;
private int VIN;
int getVIN() {
return VIN;
}
Vehicle() { VIN = highestVIN++; }
Vehicle (String owner) { this(); this.owner = owner; }
public static void main(String[] args) {
Vehicle a = new Vehicle("Larry Bird");
Vehicle b = new Vehicle("Mark Jackson");
System.out.println("VIN: " + a.getVIN() + " belongs to " + a.getOwner());
System.out.println("VIN: " + b.getVIN() + " belongs to " + b.getOwner());
}
}```
6. 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.

```class Vehicle {
private int currentSpeed;
int getSpeed() { return currentSpeed; }
void changeSpeed(int newSpeed) { currentSpeed = newSpeed; }
void stop() { currentSpeed = 0; }
private int currentDirection;
int getCurrentDirection() { return currentDirection; }
void setDirection(int newDirection) { currentDirection = newDirection % 360; }
private String owner;
int getOwner() { return owner; }
void setOwner(String newOwner) { owner = newOwner; }
private static int highestVIN;
private int VIN;
Vehicle() { VIN = highestVIN++; }
Vehicle (String owner) { this(); this.owner = owner; }
public static void main(String[] args) {
// ...
}
}```
7. 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.

```class Vehicle {
private int currentSpeed;
int getSpeed() { return currentSpeed; }
void changeSpeed(int newSpeed) { currentSpeed = newSpeed; }
void stop() { currentSpeed = 0; }
private int currentDirection;
int getCurrentDirection() { return currentDirection; }
void setDirection(int newDirection) { currentDirection = newDirection % 360; }
static final String TURN_LEFT = "Turn left";
static final String TURN_LEFT = "Turn left";
void turn(int degrees) {
currentDirection = (currentDirection + degrees) % 360;
}
void turn(String direction) {
if (direction.equals(left)) {
currentDirection = (currentDirection + 90) % 360;
} else { //default
currentDirection = (currentDirection - 90) % 360;
}
}
private String owner;
int getOwner() { return owner; }
void setOwner(String newOwner) { owner = newOwner; }
private static int highestVIN;
private int VIN;
Vehicle() { VIN = highestVIN++; }
Vehicle (String owner) { this(); this.owner = owner; }
public static void main(String[] args) {
// ...
}
}```
8. Add a static method to `Vehicle` that returns the highest identification number used so far.

```class Vehicle {
private int currentSpeed;
int getSpeed() { return currentSpeed; }
void changeSpeed(int newSpeed) { currentSpeed = newSpeed; }
void stop() { currentSpeed = 0; }
private int currentDirection;
int getCurrentDirection() { return currentDirection; }
void setDirection(int newDirection) { currentDirection = newDirection % 360; }
static final String TURN_LEFT = "Turn left";
static final String TURN_LEFT = "Turn left";
void turn(int degrees) { currentDirection = (currentDirection + degrees) % 360; }
void turn(String direction) {
if (direction.equals(left)) { currentDirection = (currentDirection + 90) % 360; }
else { currentDirection = (currentDirection - 90) % 360; }
}
private String owner;
int getOwner() { return owner; }
void setOwner(String newOwner) { owner = newOwner; }
private static int highestVIN;
static int highestVIN() {
return highestVIN;
}
private int VIN;
Vehicle() { VIN = highestVIN++; }
Vehicle (String owner) { this(); this.owner = owner; }
public static void main(String[] args) {
// ...
}
}```
9. Add a `toString` method to `Vehicle`.
```class Vehicle {
String toString() {
return "The radar reports: VIN " +  VIN +
" owned by " + owner +
" heading " + currentDirection +
" (degrees) " +
" at a speed of " + speed);
}
private int currentSpeed;
int getSpeed() { return currentSpeed; }
void changeSpeed(int newSpeed) { currentSpeed = newSpeed; }
void stop() { currentSpeed = 0; }
private int currentDirection;
int getCurrentDirection() { return currentDirection; }
void setDirection(int newDirection) { currentDirection = newDirection % 360; }
static final String TURN_LEFT = "Turn left";
static final String TURN_LEFT = "Turn left";
void turn(int degrees) { currentDirection = (currentDirection + degrees) % 360; }
void turn(String direction) {
if (direction.equals(left)) { currentDirection = (currentDirection + 90) % 360; }
else { currentDirection = (currentDirection - 90) % 360; }
}
private String owner;
int getOwner() { return owner; }
void setOwner(String newOwner) { owner = newOwner; }
private static int highestVIN;
static int highestVIN() { return highestVIN; }
private int VIN;
Vehicle() { VIN = highestVIN++; }
Vehicle (String owner) { this(); this.owner = owner; }
public static void main(String[] args) {
// ...
}
}```

10. Define a class of `Fractions`. I leave this out, as part of it was presented in the lecture. This problem used to have an extra-part (that I mention below).

For the ambitious:

Add a private method `lcm` to the class `Fraction` that takes two `int`s and returns their least common multiple. (For example, `lcm(15, 12)` is `60`. Hint: use `gcd`). Modify `minus` and `plus` in `Fraction` to use `lcm`.

The part for the very ambitious:

One could prove the following:

`lcm(p, q) * gcd(p, q) = p * q`
And the rest is easy.

If you have any questions please let us know.

Last updated: Jul 28, 2002 by Adrian German for A201