Class Definitions

Naive Ticket Machine

A simple ticket machine works by having a customer insert money and the ticket machine issues a ticket (a naive ticket machine).

Compile the naive ticket machine class and create a new object.  Explore the methods: getBalance, getPrice, insertMoney, printTicket. After inserting money you should the balance increase. After buying a ticket you should see the balance fall. What are the limitations of this program?

Here is the code:

/**
* TicketMachine models a naive ticket machine that issues
* flat-fare tickets.
* The price of a ticket is specified via the constructor.
* It is a naive machine in the sense that it trusts its users
* to insert enough money before trying to print a ticket.
* It also assumes that users enter sensible amounts.
*
* @author David J. Barnes and Michael Kolling
* @version 2006.03.30
*/
public class TicketMachine
{
// The price of a ticket from this machine.
private int price;
// The amount of money entered by a customer so far.
private int balance;
// The total amount of money collected by this machine.
private int total;

/**
* Create a machine that issues tickets of the given price.
* Note that the price must be greater than zero, and there
* are no checks to ensure this.
*/
public TicketMachine(int ticketCost)
{
price = ticketCost;
balance = 0;
total = 0;
}

/**
* Return the price of a ticket.
*/
public int getPrice()
{
return price;
}

/**
* Return the amount of money already inserted for the
* next ticket.
*/
public int getBalance()
{
return balance;
}

/**
* Receive an amount of money in cents from a customer.
*/
public void insertMoney(int amount)
{
balance = balance + amount;
}

/**
* Print a ticket.
* Update the total collected and
* reduce the balance to zero.
*/
public void printTicket()
{
// Simulate the printing of a ticket.
System.out.println("##################");
System.out.println("# The BlueJ Line");
System.out.println("# Ticket");
System.out.println("# " + price + " cents.");
System.out.println("##################");
System.out.println();

// Update the total collected with the balance.
total = total + balance;
// Clear the balance.
balance = 0;
}
}

The outer part of a class is its definition:

public class TicketMachine
{

}

Try reversing 'public' and 'class' - is the error message <identifier expected> helpful? Try deleting 'public' - does this have any effect?

The fields, constructors and methods of a class are defined inside the braces. Fields store data; constructors set up objects; methods provide behaviours. Examine these in the code above.

Fields

Fields include price, balance and total; these would be called variables in Pascal: in Java they are called instance variables.

private int price;
private int balance;
private int total;

All instantiated objects reserve space for variables.

Fields are nearly always declared as private.

Constructors

Constructors have the same name as the class:

public TicketMachine(int ticketCost)
{
price = ticketCost;
balance = 0;
total = 0;
}

Note that the class definition has no parameters and also includes the word 'public': this distinguishes the class header from the constructor.

The fields are initialised in the constructor so when a ticket machine is created it has certain fields set. These values can be changed with methods that access the individual variables. When a ticket machine is created its price is entered. Here the price is set to 1:

Parameters

Constructors and methods receive data via parameters. The naive ticket machine constructor has a single parameter for its cost. The parameter in the constructor header is a formal parameter; the parameter in a call to the constructor is an actual parameter. A formal parameter has scope limited to the body of its constructor or method - it is a local variable. The scope of a field is global to the class.

The lifetime of a parameter is limited to one call of the constructor or method. The lifetime of a field is the same as that of the object to which it belongs.

Assignment

e.g.: balance = 0;

Data type must match the type declaration of the field.

Accessor Methods

The getPrice method is as follows:

public int getPrice()
{
return price;
}

The first line of a method is called its signature. Field declarations are similar but have no brackets (for optional parameters) and a signature has no semi-colon:

private int price;

The method's body is inside the curly braces. Code inside curly braces is known as a 'block'.

The 'int' before the name of the method is the return type (found at the end of a function header in Pascal). Constructors never have return types.

The getPrice method returns the value of a field; it does not change it so it called an accessor method. getBalance is a similar method:

public int getBalance()
{
return balance;
}

Mutator Methods

The methods insertMoney and printTicket change the value of one or more fields and so are called mutator methods.

public void insertMoney(int amount)
{
balance = balance + amount;
}

The signature of insertMoney has a void return type because it does not return a value but rather changes the value of balance.

public void printTicket()
{
// Simulate the printing of a ticket.
System.out.println("##################");
System.out.println("# The BlueJ Line");
System.out.println("# Ticket");
System.out.println("# " + price + " cents.");
System.out.println("##################");
System.out.println();

// Update the total collected with the balance.
total = total + balance;
// Clear the balance.
balance = 0;
}

The signature of printTicket also has a void return type for the same reason. Data is output by use of the println method of the System.out object that is built into the Java language. Note the use of the concatenation operator to include substrings (here values from fields).

Exercise: Add a method called prompt to the ticketMachine class. This should have a void return type and should have no parameters. The body should provide a message like 'Please insert the correct money'.

Exercise: Add a showPrice method to the ticketMachine class. This should have a void return type and should have no parameters. The body should provide a message like 'The price of a ticket is xy cents'.

Exercise: create two ticket machines with different prices and compare outputs.

Exercise: modify the constructor of TicketMachine by removing the parameter. Fix the ticket price at 1000. What effect does this have when the ticketMachine objects are constructed?

Improved Ticket Machine

The naive ticket machine had:

Code:

/**
* TicketMachine models a ticket machine that issues
* flat-fare tickets.
* The price of a ticket is specified via the constructor.
* Instances will check to ensure that a user only enters
* sensible amounts of money, and will only print a ticket
* if enough money has been input.
*
* @author David J. Barnes and Michael Kolling
* @version 2006.03.30
*/
public class TicketMachine
{
// The price of a ticket from this machine.
private int price;
// The amount of money entered by a customer so far.
private int balance;
// The total amount of money collected by this machine.
private int total;

/**
* Create a machine that issues tickets of the given price.
*/
public TicketMachine(int ticketCost)
{
price = ticketCost;
balance = 0;
total = 0;
}

/**
* @Return The price of a ticket.
*/
public int getPrice()
{
return price;
}

/**
* Return The amount of money already inserted for the
* next ticket.
*/
public int getBalance()
{
return balance;
}

/**
* Receive an amount of money in cents from a customer.
* Check that the amount is sensible.
*/
public void insertMoney(int amount)
{
if(amount > 0) {
balance = balance + amount;
}
else {
System.out.println("Use a positive amount: " +
amount);
}
}

/**
* Print a ticket if enough money has been inserted, and
* reduce the current balance by the ticket price. Print
* an error message if more money is required.
*/
public void printTicket()
{
if(balance >= price) {
// Simulate the printing of a ticket.
System.out.println("##################");
System.out.println("# The BlueJ Line");
System.out.println("# Ticket");
System.out.println("# " + price + " cents.");
System.out.println("##################");
System.out.println();

// Update the total collected with the price.
total = total + price;
// Reduce the balance by the prince.
balance = balance - price;
}
else {
System.out.println("You must insert at least: " +
(price - balance) + " more cents.");

}
}

/**
* Return the money in the balance.
* The balance is cleared.
*/
public int refundBalance()
{
int amountToRefund;
amountToRefund = balance;
balance = 0;
return amountToRefund;
}
}

The insertMoney method has been changed:

public void insertMoney(int amount)
{
if(amount > 0) {
balance = balance + amount;
}
else {
System.out.println("Use a positive amount: " +
amount);
}
}

The amount is only added to the balance if the amount is greater than zero. Likewise the printTicket method:

public void printTicket()
{
if(balance >= price) {
// Simulate the printing of a ticket.
System.out.println("##################");
System.out.println("# The BlueJ Line");
System.out.println("# Ticket");
System.out.println("# " + price + " cents.");
System.out.println("##################");
System.out.println();
// Update the total collected with the price.
total = total + price;
// Reduce the balance by the prince.
balance = balance - price;
}
else {
System.out.println("You must insert at least: " +
(price - balance) + " more cents.");
}
}

A ticket is only printed if the balance is greater than the price of the ticket.

The refund_Balance method includes a local variable called amount:

public int refundBalance()
{
int amountToRefund;
amountToRefund = balance;
balance = 0;
return amountToRefund;
}

This is used to give the money in the balance as change and to reset the balance to zero. This is not a field because it is defined inside a method. Local variables do not need to be declared as private or public because their scope is limited to the method and their lifetime is limited to the call of the method. Fields have their scope and lifetime at the level of the class.

Exercise: Rewrite the printTicket method with a local variable amountLeftToPay. This should be set to price minus balance; if the amountLeftToPay is greater than or equal to zero then the ticket is issued, otherwise it is not.

Exercise: write a program that implements a ticket machine that can issue tickets of different prices.

Student Class

Here is the code:


/**
* The Student class represents a student in a student administration system.
* It holds the student details relevant in our context.
*
* @author Michael Kolling and David Barnes
* @version 2006.03.30
*/
public class Student
{
// the student's full name
private String name;
// the student ID
private String id;
// the amount of credits for study taken so far
private int credits;

/**
* Create a new student with a given name and ID number.
*/
public Student(String fullName, String studentID)
{
name = fullName;
id = studentID;
credits = 0;
}

/**
* Return the full name of this student.
*/
public String getName()
{
return name;
}

/**
* Set a new name for this student.
*/
public void changeName(String replacementName)
{
name = replacementName;
}

/**
* Return the student ID of this student.
*/
public String getStudentID()
{
return id;
}

/**
* Add some credit points to the student's accumulated credits.
*/
public void addCredits(int additionalPoints)
{
credits += additionalPoints;
}

/**
* Return the number of credit points this student has accumulated.
*/
public int getCredits()
{
return credits;
}

/**
* Return the login name of this student. The login name is a combination
* of the first four characters of the student's name and the first three
* characters of the student's ID number.
*/
public String getLoginName()
{
return name.substring(0,4) + id.substring(0,3);
}

/**
* Print the student's name and ID number to the output terminal.
*/
public void print()
{
System.out.println(name + " (" + id + ")");
}
}

The getLoginName method is as follows:

public String getLoginName()
{
return name.substring(0,4) + id.substring(0,3);
}

This returns a Login Name formed by concatenating the first four characters of name with the first three characters of the numeric id. The string class has an accessor method called substring that allows part of a string to be returned. What if name has only 3 characters?

Home Page