| 3.2 |
Specifying the Public Interface
of a Class |
 |
 |
In this section, we will discuss the process of specifying the behavior
of a class. Imagine that you are a member of a team that works on banking software.
A fundamental concept in banking is a
bank
account. Your task is to understand the design of a
BankAccount class
so that you can implement it, which in turn allows other programmers on the
team to use it.
You need to know exactly what features of a bank account need to be implemented.
Some features are essential (such as deposits), whereas others are not important
(such as the gift that a customer may receive for opening a bank account).
Deciding which features are essential is not always an easy task. We will revisit
that issue in Chapters 8 and 12. For now, we will assume that a competent designer
has decided that the following are considered the essential operations of a
bank account:
|
·
|
Deposit money
|
 |
·
|
Withdraw money
|
 |
·
|
Get the current balance
|
 |
|
In Java, operations are expressed as method calls. To figure out the exact
specification of the method calls, imagine how a programmer would carry out
the bank account operations. We'll assume that the variable
harrysChecking contains
a reference to an object of type
BankAccount.
We want to support method calls such as the following:
harrysChecking.deposit(2000);
harrysChecking.withdraw(500);
System.out.println(harrysChecking.getBalance());
Note that the first two methods are mutators. They modify the balance of the
bank account and don't return a value. The third method is an accessor. It
returns a value that you can print or store in a variable.
As you can see from the sample calls, the
BankAccount class
should define three methods:
|
·
|
public void
deposit(double amount)
|
 |
·
|
public void
withdraw(double amount)
|
 |
·
|
public double
getBalance()
|
 |
|
Recall from Chapter 2 that
double denotes
the double-precision floating-point type, and
void indicates
that a method does not return a value.
When you define a method, you also need to provide the method
body,
consisting of statements that are executed when the method is called.
public void deposit(double amount)
{
body—filled in later
}
You will see in Section 3.5 how to fill in the method body.
Every method definition contains the following parts:
|
·
|
An access specifier (usually public)
|
 |
·
|
The return type (such
as void or double)
|
 |
·
|
The name of the method (such as deposit)
|
 |
·
|
A list of the parameters of
the method (if any), enclosed in parentheses (such as double
amount)
|
 |
·
|
The body of
the method: statements enclosed in braces
|
 |
|
The access specifier controls which other methods can call this method.
Most methods should be declared as public.
That way, all other methods in a program can call them. (Occasionally, it can
be useful to have private methods.
They can only be called from other methods of the same class.)
The return type is the type of the output value. The deposit method
does not return a value, whereas the getBalance method
returns a value of type double.
Each parameter (or input) to the method has both a type and a name. For
example, the deposit method has
a single parameter named amount of
type double. For each parameter,
choose a name that is both a legal variable name and a good description of
the purpose of the input.
Next, you need to supply constructors. We will want to construct bank accounts
that initially have a zero balance, by using the default constructor:
BankAccount harrysChecking = new BankAccount();
What if a programmer who uses our class wants to start out with another balance?
A second constructor that sets the balance to an initial value will be useful:
BankAccount momsSavings = new BankAccount(5000);
To summarize, it is specified that two constructors will be provided:
|
·
|
public BankAccount()
|
 |
·
|
public BankAccount(double
initialBalance)
|
 |
|
A
constructor is very similar to
a method, with two important differences.
|
·
|
The name of the constructor is always the same
as the name of the class (e.g., BankAccount)
|
 |
·
|
Constructors have no return type (not even void)
|
 |
|
Just like a method, a constructor also has a body—a sequence of statements
that is executed when a new object is constructed.
public BankAccount()
{
body-filled in later
}
The statements in the constructor body will set the internal data of the object
that is being constructed—see Section 3.5.
Don't worry about the fact that there are two constructors with the same
name—all constructors of a class
have the same name, that is, the name of the class. The compiler can tell them
apart because they take different parameters.
When defining a class, you place all constructor and method definitions
inside, like this:
public class BankAccount
{
// Constructors
public BankAccount()
{
body-filled in later
}
public BankAccount(double initialBalance)
{
body-filled in later
}
// Methods
public void deposit(double amount)
{
body-filled in later
}
public void withdraw(double amount)
{
body-filled in later
}
public double getBalance()
{
body-filled in later
}
private fields-filled in later
}
You will see how to supply the missing pieces in the following sections.
The public constructors and methods of a class form the
public
interface of the class. These are the operations that any programmer
can use to create and manipulate
BankAccount objects.
Our
BankAccount class is simple,
but it allows programmers to carry out all of the important operations that
commonly occur with bank accounts. For example, consider this program segment,
authored by a programmer who uses the
BankAccount class.
These statements transfer an amount of money from one bank account to another:
// Transfer from one account to another
double transferAmount = 500;
momsSavings.withdraw(transferAmount);
harrysChecking.deposit(transferAmount);
And here is a program segment that adds interest to a savings account:
double interestRate = 5; // 5% interest
double interestAmount
= momsSavings.getBalance() * interestRate / 100;
momsSavings.deposit(interestAmount);
As you can see, programmers can use objects of the
BankAccount class
to carry out meaningful tasks, without knowing how the
BankAccount objects
store their data or how the
BankAccount methods
do their work.
Of course, as implementors of the BankAccount class,
we will need to supply the internal details. We will do so in Section 3.5.
First, however, an important step remains: documenting the
public interface. That is the topic of the next section.