Back: Next coming
Up: Tutorial
Forward: The Savings class
 
Top: GNU Smalltalk User's Guide
Contents: Table of Contents
Index: Class index
About: About this document

5.5 Two Subclasses for the Account Class

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.

5.5.1 The Savings class  One of the two subclasses we'll put together
5.5.2 The Checking class  And here is the other
5.5.3 Writing checks  Only in Smalltalk, of course


5.5.1 The Savings class

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
       instanceVariableNames: 'interest'
       classVariableNames: ''
       poolDictionaries: ''
       category: nil !

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.
 
   !Savings methodsFor: 'initialization'!
   init
       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:
 
   !Savings methodsFor: 'interest'!
   interest: amount
       interest := interest + amount.
       self deposit: amount
   !
   clearInterest
       | oldinterest |

       oldinterest := interest.
       interest := 0.
       ^oldinterest
   ! !

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.(23)

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.(24)


5.5.2 The Checking class

Our second subclass of Account represents a checking account. We will keep track of two facets:

  • What check number we are on

  • How many checks we have left in our checkbook

We will define this as another subclass of Account:
 
  Account subclass: #Checking
       instanceVariableNames: 'checknum checksleft'
       classVariableNames: ''
       poolDictionaries: ''
       category: nil !

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.
 
   !Checking methodsFor: 'Initialization'!
   init
       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.


5.5.3 Writing checks

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:
 
   !Checking methodsFor: 'spending'!
   newChecks: number count: checkcount
       checknum := number.
       checksleft := checkcount
   !

   writeCheck: amount
       | 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:
 
   Smalltalk at: #c put: (Checking new) !
   c printNl !
   c deposit: 250 !
   c printNl !
   c newChecks: 100 count: 50 !
   c printNl !
   (c writeCheck: 32) printNl !
   c printNl !

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.




This document was generated on May, 12 2002 using texi2html