Next: , Up: Creating subclasses  


6.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 [
       | 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


Footnotes

(28)

self is much like super, except that self will start looking for a method at the bottom of the type hierarchy for the object, while super starts looking one level up from the current level. Thus, using super forces inheritance, but self will find the first definition of the message which it can.

(29)

Of course, in a real accounting system we would never discard such information—we’d probably throw it into a Dictionary object, indexed by the year that we’re finishing. The ambitious might want to try their hand at implementing such an enhancement.


Next: , Up: Creating subclasses