Smalltalk中的自我和超级

cad*_*ebe 4 inheritance smalltalk class

我正在写Smalltalk的第一个程序.我有一个实现方法的超类,然后是一个继承自这个类的子类,并覆盖超类的方法.我认为我对自我语句有困难,因为当子类调用方法时,会调用超类和子类的平衡,因此存在累积效应,而不是 - 或选择.

这是有问题的代码的摘录:

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.
    ]
]
Run Code Online (Sandbox Code Playgroud)

我该如何纠正这个问题?

Lea*_*lia 7

因此,问题(据我所知)是,在您的实施中,PersonalAccount首先应用20%(in super calculateInterest)的利息,然后再增加25%,而目的是仅应用25%的利息.

在不重复两个类中的代码的情况下解决此问题的最佳方法是分解interest方法,如下所示:

Account >> interest
    ^0.2

PersonalAccount >> interest
    ^0.25
Run Code Online (Sandbox Code Playgroud)

现在,您可以calculateInterest从子类中删除并仅将方法保留在超类中

Account >> calculateInterest
    balance := self getBalance * self interest + self getBalance
Run Code Online (Sandbox Code Playgroud)

以这种方式,当所述接收器#calculateInterest是一个Account平衡将在20%的增加,并且当所述接收器是PersonalAccount,平衡会增加25%.

在一个侧面说明,我会建议更换选择getBalancebalance.在具有类C语法的语言中,除了前缀getset前缀以区分两个动作之外没有其他选择.但是,在Smalltalk中,使用冒号:作为消息名称和参数之间的分隔符,使得前缀的使用变得多余:您可以使用它balance来读取ivar并balance:编写它.请注意,这不仅仅是为了简单起见,它还使您的代码更接近自然语言(account balanceaccount getBalance.相比).


Uko*_*Uko 5

看起来你根本就没有必要打电话 super calculateInterest

但是为了更好的设计考虑这个实现:

Object subclass: Account [

        | balance |

        ...

        getBalance [    
            ^balance
        ]

        getInterest [
            ^ 0.2
        ]


        calculateInterest [
            balance:= self getBalance * self getInterest + self getBalance.
        ]
    ]

Account subclass: PersonalAccount [

    ... 

    getInterest [
            ^ 0.25
   ]
]
Run Code Online (Sandbox Code Playgroud)

或者您可以将兴趣作为参数,或者您可以将兴趣作为层次结构根的子类责任,然后每个子类应重新定义它.

基本上你说的是:

  • 在账户中根据利息重新计算余额是"xyz"
  • 在PersonalAccount中,根据兴趣重新计算余额为:
    • 第一,基于超级课程重新计算
    • "xyz"(稍加修改)

不要以为你必须覆盖一个方法并调用super你想要描述的内容.