cadebe
cadebe

Reputation: 691

Self and super in Smalltalk

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

Answers (2)

Leandro Caniglia
Leandro Caniglia

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

Uko
Uko

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:

  • In Account recalculation of a balance based on interest is "xyz"
  • In PersonalAccount recalculation of a balance based on interest is:
    • firs, recalculation of it based on a super class
    • "xyz" (slightly modified)

Don't think that you have to override a method and call super think what you are describing.

Upvotes: 5

Related Questions