本章接着上一章演示如何创建类和创建子类。在本章你将要创建两个特殊的Account的子类:Checking和Savings。我们将继承Account的能力,同时特意使用两个对象,以便更好地管理账号特定的内容。
我们创建Saving类作为Account的子类。用来像Account那样存钱,但是新增一个属性,用来依据结余支付利息。我们Saving作为Account的子类:
Account subclass: Savings [ | interest | |
这已经告诉我们:实例化变量将会计算利息支付。因此除继承Account得到的spend:和deposit:消息外,我们将需要定义一个方法去添加利息存款,然后每年在付过税后清除利息变量。我们先来定义一个方法分配一个性的账户。我们确保利息的范围从0开始。
我们可以在Account的子类里作这一切:存储范围
We can do so within the Account subclass: Savings scope, which we have not closed above.
init [ <category: 'initialization'> interest := 0. ^super init ] |
再次调用时父要处理new消息,创建一个大小适当的对象。在创建后,父仍旧发送init消息给新对象。作为Account的子类,新的对象先收到init消息;设置我们的实例变量,之后init消息被向上传递到链,其父处理他的初始化部分。
随着我们的新账户Saving被创建,我们可以定义两个方法来处理这个帐号的特殊操作
interest: amount [ interest := interest + amount. self deposit: amount ] clearInterest [ | oldinterest | oldinterest := interest. interest := 0. ^oldinterest ] |
现在定义完了,现在闭合整个类
] |
第一个方法告诉我们添加我们添加amount来计算总利息。self deposit: amount这一行让Smalltalk给对象自己发送了一个消息 ,在这里是deposit: amount。这之后英文Smalltalk查找deposit:模块,实际在父中寻找到后运行,修改我们的总结语balance变量。
你也许会纳闷为什么我们不简单的 balance := balance + amount。答案依赖于面对象语言尤其是Smalltalk的一个原则。我们的目标是仅仅编码一个技术一次,然后再需要的时候重用。如果我们直接在这里使用balance := balance + amount。当需要修改balance表示存款的时候就有两个地方需要改。这里或许看起来没什么实用的区别。但是考虑到假如以后我们决定开始继续这种记录存款总数的方法。假如我们都写成balance := balance + amount 在每一个地方。当需要修改balance时,我们不得不搜寻每一个用到的地方来修改。如果发送自生deposit:消息,我们仅需修改这个方法一次,所有的接收者都会自动获取到最新的正确的方式来更新balance。
第二个方法chearInterest很简单。我们创建了一个缓存变量oldinterest来保存当前利息总数。我们在新年开始之后归零,用返回的之前的利息作为结果。所以我们在年末会计可以看到我们产生了多少利息
Checking类: 这里还有其他的东西
我们第二个Account的子类代表了支票账号。我们将跟踪两个面:
我们的支票的总数
开处的支票总数
我们将定义另一个Account的子类:
Account subclass: Checking [ | checknum checksleft | |
我们有两个实例变量,但我们仅需要初始其中一个,如果没有开处支票,现在的字票数就不是问题。记住,我们的父类给我门发送init消息,我们不需要我们的类使用特殊的new函数,我们的父将会作有我们需要的工作。
init [ <category: 'initialization'> checksleft := 0. ^super init ] |
如同在Savings中,我们继承了大量功能从我们的父类(superclass)Account。在初始化中我们仅仅设置支票总数为0,而没有设置checknum。我等会在父类中进行初始化。
我们将在添加通过支票花钱的方法后结束本章。发送消息,更新变量的机关类似这样:
newChecks: number count: checkcount [ <category: 'spending'> checknum := number. checksleft := checkcount ] writeCheck: amount [ <category: 'spending'> | num | num := checknum. checknum := checknum + 1. checksleft := checksleft - 1. self spend: amount. ^ num ] ] |
newChecks: 用支票填充我们的支票本。我们记录我们最初的的支票数,更新支票簿里的支票总数。
writeCheck:仅仅下一个支票数,之后提升支票数,记录支票总额。消息 self spend: amount给对象自生发送spend:消息。导致这个方法被Smalltalk查找。最终在父类Account中找到,我们的总额被更新反应出我们的消费。
可以试试下面这些例子:
c := Checking new c deposit: 250 c newChecks: 100 count: 50 c writeCheck: 32 c |
消遣以下,或许你想为Checking类添加printOn:消息,这样就可以看到Checking的特殊信息了。
在这一章,你已经知道如何为自己的类添加子类了。你也他先了新的方法,从父类继承方法。这些技术提供了结构化解决问题的主要方式。在下一章我们将深入语言机制和类型的细节,同时提供如何在Smalltalk中调试的细节。
您必须登录才能发表评论。