I'm not sure I'm eloquent enough to put it over very convincingly but, as I recall, the argument goes something along the lines of:
Given a Money
object; it might contain an amount
field:class Money1
{
public int amount;
}
We could then use it as follows: Money1 m11 = new Money1();
Money1 m12 = new Money1();
Money1 m13 = new Money1();
m11.amount = 3;
m12.amount = 5;
m13.amount = m11.amount + m12.amount;
Most comentators simply advise that the amount
variable should be private and should be accessed via a matching pair of public getAmount
and setAmount
methods:class Money2
{
private int amount;
public int getAmount() { return amount; }
public void setAmount(int newAmount){ amount = newAmount; }
}
This is a minimal solution which is better than nothing, but not much. To add two Money objects, we might write the following code:
m21.setAmount(3);
m22.setAmount(5);
m23.setAmount(m21.getAmount() + m22.getAmount());
Unfortunately, this is procedural not object-oriented thinking. The manipulation of the Money
objects is still taking place outside the object. We have encapsulated the variable but then immediately re-exposed it (and its int
implementation) via the accessor methods without really achieving anything useful. The manipulation of the money is taking place as integer mathmatics outside the Money
object.
What is really required is that the concepts required for manipulating money are encapsulated inside the Money
object and that the amount
variable and how it is implemented internally becomes further hidden. Thus the raw accessors become package protected and the public methods completely hide the internal implementation:class Money3
{
private int amount;
// Raw data accessors shouldn't be public.
int getAmount() { return amount; }
void setAmount(int newAmount){ amount = newAmount; }
public Money3(int initialAmount) { amount = initialAmount; }
/** This method (and possibly others) replaces the public getAmount. */
public String toString()
{
// Improve this code to properly format output..
return new Integer(amount).toString();
}
/** This method (and possibly others) replaces the public setAmount. */
public void add(Money3 moreMoney)
{
amount += moreMoney.getAmount();
}
}
Other than the constructor (and this too could be improved), all information relating to the internal storage and manipulation within the Money
object is now hidden from the user. The user of the Money
object now requests the required services from the object rather than performing those services (e.g. adding money amounts) for the object.
Money3 m31 = new Money3(3);
Money3 m32 = new Money3(5);
Money3 m33 = new Money3(0);
m33.add(m31);
m33.add(m32);
Vince.