|
5.3 The Smalltalk class hierarchyWhen programming in Smalltalk, you sometimes need to create new kinds of objects, and define what various messages will do to these objects. In the next chapter we will create some new classes, but first we need to understand how Smalltalk organizes the types and objects it contains. Because this is a pure "concept" chapter, without any actual Smalltalk code to run, we will keep it short and to the point.
5.3.1 Class
|
Object Animals Parrots Pigs |
This means that Animals, Parrots, and Pigs are all direct descendants of Object, and are not descendants of each other.
Now we must define how each animal responds to each kind of message.
Animals eat --> Say ``I have now eaten'' sing --> Error snort --> Error Parrots eat --> Say ``I have now eaten'' sing --> Say ``Tweet'' snort --> Error Pigs eat --> Say ``I have now eaten"'' sing --> Error snort --> Say ``Oink'' |
Notice how we kept having to indicate an action for eat. An experienced object designer would immediately recognize this as a clue that we haven't set up our hierarchy correctly. Let's try a different organization:
Object Animals Parrots Pigs |
That is, Parrots inherit from Animals, and Pigs from Parrots. Now Parrots inherit all of the actions from Animals, and Pigs from both Parrots and Animals. Because of this inheritance, we may now define a new set of actions which spares us the redundancy of the previous set:
Animals eat --> Say ``I have now eaten'' sing --> Error snort --> Error Parrots sing --> Say ``Tweet'' Pigs snort --> Say ``Oink'' |
Because Parrots and Pigs both inherit from Animals, we have only had to define the eat action once. However, we have made one mistake in our class setup--what happens when we tell a Pig to sing? It says "Tweet", because we have put Pigs as an inheritor of Parrots. Let's try one final organization:
Object Animals Parrots Pigs |
Now Parrots and Pigs inherit from Animals, but not from each other. Let's also define one final pithy set of actions:
Animals eat --> Say ``I have eaten'' Parrots sing --> Say ``Tweet'' Pigs snort --> Say ``Oink'' |
The change is just to leave out messages which are inappropriate. If Smalltalk detects that a message is not known by an object or any of its ancestors, it will automatically give an error--so you don't have to do this sort of thing yourself. Notice that now sending sing to a Pig does indeed not say "Tweet"---it will cause a Smalltalk error instead.
The goal of the class hierarchy is to allow you to organize objects into a relationship which allows a particular object to inherit the code of its ancestors. Once you have identified an effective organization of types, you should find that a particular technique need only be implemented once, then inherited by the children below. This keeps your code smaller, and allows you to fix a bug in a particular algorithm in only once place--then have all users of it just inherit the fix.
You will find your decisions for adding objects change as you gain experience. As you become more familiar with the existing set of objects and messages, your selections will increasingly "fit in" with the existing ones. But even a Smalltalk pro stops and thinks carefully at this stage, so don't be daunted if your first choices seem difficult and error-prone.