![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
This chapter continues from the previous chapter in demonstrating how one creates classes and subclasses in Smalltalk. In this chapter we will create two special subclasses of Account, known as Checking and Savings. We will continue to inherit the capabilities of Account, but will tailor the two kinds of objects to better manage particular kinds of accounts.
6.5.1 The Savings class One of the two subclasses we'll put together 6.5.2 The Checking class And here is the other 6.5.3 Writing checks Only in Smalltalk, of course
We create the Savings class as a subclass of Account. It holds money, just like an Account, but has an additional property that we will model: it is paid interest based on its balance. We create the class Savings as a subclass of Account.
Account subclass: Savings [ | interest | |
This is already telling something:
the instance variable interest
will accumulate interest
paid. Thus, in addition to the spend:
and
deposit:
messages which we inherit from our parent,
Account, we will need to define a method to add in interest
deposits, and a way to clear the interest variable (which
we would do yearly, after we have paid taxes). We first define
a method for allocating a new account--we need to make sure that the
interest field starts at 0.
We can do so within the Account subclass: Savings
scope,
which we have not closed above.
init [ <category: 'initialization'> interest := 0. ^super init ] |
Recall that the parent took care of the new
message, and
created a new object of the appropriate size. After creation,
the parent also sent an init
message to the new
object. As a subclass of Account, the new object will
receive the init
message first; it sets up its own
instance variable, and then passes the init
message up the
chain to let its parent take care of its part of the
initialization.
With our new Savings
account created, we can define
two methods for dealing specially with such an account:
interest: amount [ interest := interest + amount. self deposit: amount ] clearInterest [ | oldinterest | oldinterest := interest. interest := 0. ^oldinterest ] |
We are now finished, and close the class scope:
] |
The first method says that we add the amount
to our
running total of interest. The line self deposit: amount
tells Smalltalk to send ourselves a message, in this case
deposit: amount
. This then causes Smalltalk to look up
the method for deposit:
, which it finds in our parent,
Account. Executing this method then updates our overall
balance.(28)
One may wonder why we don't just replace this with the
simpler balance := balance + amount
. The answer lies
in one of the philosophies of object-oriented languages in general,
and Smalltalk in particular. Our goal is to encode a
technique for doing something once only, and then re-using
that technique when needed. If we had directly encoded
balance := balance + amount
here, there would have been
two places that knew how to update the balance from a
deposit. This may seem like a useless difference. But consider
if later we decided to start counting the number of
deposits made. If we had encoded
balance := balance + amount
in each place that needed to
update the balance, we would have to hunt each of them down in
order to update the count of deposits. By sending self
the message deposit:
, we need only update this method
once; each sender of this message would then automatically get the correct
up-to-date technique for updating the balance.
The second method, clearInterest
, is simpler. We
create a temporary variable oldinterest
to hold the current
amount of interest. We then zero out our interest to
start the year afresh. Finally, we return the old interest
as our result, so that our year-end accountant can see how
much we made.(29)
Our second subclass of Account represents a checking account. We will keep track of two facets:
We will define this as another subclass of Account:
Account subclass: Checking [ | checknum checksleft | |
We have two instance variables, but we really only need to
initialize one of them--if there are no checks left, the current
check number can't matter. Remember, our parent class
Account will send us the init
message. We don't need our
own class-specific new
function, since our parent's will
provide everything we need.
init [ <category: 'initialization'> checksleft := 0. ^super init ] |
As in Savings, we inherit most of abilities from our superclass,
Account. For initialization, we leave checknum
alone, but set the number of checks in our checkbook to
zero. We finish by letting our parent class do its own
initialization.
We will finish this chapter by adding a method for spending money through our checkbook. The mechanics of taking a message and updating variables should be familiar:
newChecks: number count: checkcount [ <category: 'spending'> checknum := number. checksleft := checkcount ] writeCheck: amount [ <category: 'spending'> | num | num := checknum. checknum := checknum + 1. checksleft := checksleft - 1. self spend: amount. ^ num ] ] |
newChecks:
fills our checkbook with checks. We record
what check number we're starting with, and update the count
of the number of checks in the checkbook.
writeCheck:
merely notes the next check number, then
bumps up the check number, and down the check count. The
message self spend: amount
resends the message
spend:
to our own object. This causes its method to be looked
up by Smalltalk. The method is then found in our parent class,
Account, and our balance is then updated to reflect our
spending.
You can try the following examples:
c := Checking new c deposit: 250 c newChecks: 100 count: 50 c writeCheck: 32 c |
For amusement, you might want to add a printOn: message to the checking class so you can see the checking-specific information.
In this chapter, you have seen how to create subclasses of your own classes. You have added new methods, and inherited methods from the parent classes. These techniques provide the majority of the structure for building solutions to problems. In the following chapters we will be filling in details on further language mechanisms and types, and providing details on how to debug software written in Smalltalk.
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |