Java Arena
Step 2 of 5

Designing a class

Writing a class starts before the code. From a description of the problem, you decide what the class holds and what it can do. Take this one:

A train has a name and a number of cars. Every car seats 60 people. Cars can be added to the train and taken off it, but a train always keeps at least one car. We want to know how many seats a train has, and to print it like Coast Line: 3 cars, 180 seats.

Four questions lead from a description like this to a class.

1. What must each object remember? The answer gives the instance variables. A train must remember its name and its number of cars. They differ from train to train, and the cars can change: private String name; and private int cars;.

The seats are different: they follow from the number of cars. If the class kept them in a variable of their own, every method that changes the cars would also have to update the seats, and a single forgotten line would leave a train with 3 cars and 240 seats. A value that can be worked out from the others is best worked out by a method, each time it's needed. The 60 seats of a car are the same for every train, so that method can simply use the number 60.

2. What does a new object need? The answer gives the constructor's parameters. A new train needs its name. The description doesn't say how many cars a train starts with, so let it start with one: public Train(String name).

3. What can be done with it, and what do we want to know? The answers give the methods. The things that are done, adding cars and taking them off, become methods that change the object: addCar() and removeCar(). The rule "at least one car" goes into removeCar, the only place where the cars go down. The question "how many seats?" becomes a method that returns a value: seats().

4. How should it look as text? The answer goes in toString, which can call seats() instead of multiplying again.

Main.java
public class Main {
    public static void main(String[] args) {
        Train train = new Train("Coast Line");
        train.addCar();
        train.addCar();
        System.out.println(train);
        train.removeCar();
        train.removeCar();
        train.removeCar();
        System.out.println(train.seats());
    }
}
Train.java
public class Train {
    private String name;
    private int cars;

    public Train(String name) {
        this.name = name;
        this.cars = 1;
    }

    public void addCar() {
        this.cars = this.cars + 1;
    }

    public void removeCar() {
        if (this.cars > 1) {
            this.cars = this.cars - 1;
        }
    }

    public int seats() {
        return this.cars * 60;
    }

    public String toString() {
        return this.name + ": " + this.cars + " cars, " + this.seats() + " seats";
    }
}
Output
Coast Line: 3 cars, 180 seats
60
  • main doesn't need to know that the seats are worked out rather than stored: it just asks seats().
  • toString calls the object's own seats(), so "60 seats a car" is written in one place only.
  • removeCar keeps the train at one car at least, whatever main does. The third removeCar() above changes nothing.

Designs can differ. Another program might need a constructor that also takes the number of cars, or a method that tells whether a group fits on the train. Start with what the description asks for: a method that nothing calls is only more code to read.

Your task

Challenge 1 of 3

Here's a description. A garden bed is a rectangle, with a length and a width in whole meters. Every square meter has room for 4 plants. We want to know a bed's area and how many plants it has room for, and to print it like 3 x 2 m, room for 24 plants.

Write the class GardenBed, with the constructor GardenBed(int length, int width) and the methods area(), room() and toString(). Keep only what a bed must remember in instance variables. room() should use area(), and toString() should use room(). The check creates new GardenBed(3, 2) and prints its area and then the bed:

6
3 x 2 m, room for 24 plants

Challenge 2

What does this program print? It uses the Train class from the lesson.

Challenge 3

A parcel locker at a station has a number of compartments, each for one parcel. Write the class ParcelLocker:

  • ParcelLocker(int compartments) makes an empty locker with that many compartments.
  • free() returns how many compartments are empty.
  • store() puts a parcel in an empty compartment and returns true. When no compartment is free, it returns false and nothing changes. Use free() to check.
  • pickUp() takes a parcel out. When the locker is empty, nothing changes.
  • toString() returns how many compartments are in use, as in the output below.

Decide the instance variables yourself: what must a locker remember? The check makes a locker of 2 compartments, tries to store three parcels (printing what store() returns each time), prints the locker, picks up a parcel and prints free():

true
true
false
2 of 2 compartments in use
1