Reputation: 691
I am writing my first program in Smalltalk. I have a super class that implements a method, and then a sub class that inherits from this class and overrides the super class' method. I am having difficulties with the self statements, I think, because when the sub class calls the method, the balance of both that of the super class and the sub class is called, so that there is an accumulative effect, rather than an either-or choice.
This is an extract of the code in question:
Object subclass: Account [
| balance |
...
getBalance [
^balance
]
calculateInterest [
balance:= (self getBalance)*0.2 + self getBalance.
]
]
Account subclass: PersonalAccount [
...
calculateInterest [
super calculateInterest.
balance := (self getBalance)*0.25 + self getBalance.
]
]
How can I correct this problem?
Upvotes: 4
Views: 1313
Reputation: 14858
So, the problem (as I understand it) is that with your implementation the PersonalAccount
applies first an interest of 20% (in super calculateInterest
) and then an additional 25%, while the intention is to only apply an interest of 25%.
The best way to address this without repeating code in both classes is to factor out the interest
method, like this:
Account >> interest
^0.2
PersonalAccount >> interest
^0.25
Now, you can remove calculateInterest
from the subclass and leave only the method in the superclass
Account >> calculateInterest
balance := self getBalance * self interest + self getBalance
In this way, when the receiver of #calculateInterest
is an Account
the balance will be increased in 20%, and when the receiver is a PersonalAccount
, the balance will increase 25%.
On a side note, I would recommend replacing the selector getBalance
with balance
. In languages with a C-like syntax, there is no option but to prepend get
and set
prefixes to differentiate between two actions. In Smalltalk, however, the use of colon :
as the separator between the message name and the argument, makes it superfluous the use of prefixes: you can use balance
to read the ivar and balance:
to write it. Note that this is no just for the sake of simplicity, it also makes your code closer to the natural language (compare account balance
with account getBalance
.)
Upvotes: 7
Reputation: 13386
Looks like you simply don't have to call super calculateInterest
But for better design consider this implementations:
Object subclass: Account [
| balance |
...
getBalance [
^balance
]
getInterest [
^ 0.2
]
calculateInterest [
balance:= self getBalance * self getInterest + self getBalance.
]
]
Account subclass: PersonalAccount [
...
getInterest [
^ 0.25
]
]
Or you can have the interest as a parameter, or you can have the interest as subclass responsibility on the root of the hierarchy, and then each subclass should redefine it.
Essentially what you are saying is:
Don't think that you have to override a method and call super
think what you are describing.
Upvotes: 5