Delphi面向对象学习随笔五:一个真正的类 作者:巴哈姆特 (转载请注明出去并保持完整) 写在前面的话: 本篇笔记完全属于我的个人主观观点,如有错误请指正^_^ 类的定义: 首先,我想说的是,类并不是一些变量和函数简单的“拼凑”出来的。类应该是对于一个事物的抽象描述,而不是一个动作的抽象描述。怎么讲呢? 比如说:鞋子是一个事物,我们可以把它的特点抽象出来,并用计算机语言去描述成为一个类,而鞋子又分了凉鞋、皮鞋等,那么“凉鞋”和“皮鞋”则是“鞋子”的派生类。它们看上去是非常自然的。 那么,现在我有另外一个类,“初始化数据库”类,这个类看上去是非常别扭的;因为它看上去更像是一个动作。而这个“初始化数据库”类则更像是其他类中的一个“初始化数据库”方法。 编写类应该注意的问题: 一、尽可能的限制类的成员的可访问性:当你拿不准一个方法是否应该对外公开的时候,应该首先考虑定义为私有方法。 二、尽量避免暴露无需外界关心的实现细节:例如,汽车的发动机原理是不需要开汽车的司机知道的。 三、保持类本身的独立性与健壮性,不应该对类的使用者有任何想当然的假设或强制的要求:比如如果写了一个类,其某个属性不能是负值,则应该在类内部显式处理负值的情况,并给出适当的出错处理,而不能在注释中写上“{在创建类以后,请初始化xx属性为正数,如果初始化为负数的话类将会崩溃},”这样的将责任推给使用者的宣言。 四、让代码阅读比编写更方便:因为代码的阅读次数比编写次数要多的多。 五、尽可能的降低类与类之间的耦合度:除非是有包含关系,如果是平等关系的类,应该避免在类中的方法依赖于其他类中的属性或方法。 遇见问题时的处理方法: 假设、我们有一个基类“鸟类”(TBird),类中有一个通用方法“飞”(Fly)。并且为这个类派生了一些子类“海鸥”(TGull)等、这些看起来似乎很正常,但是当我们在定义“鸵鸟”(TOstrich)的时候,发现鸵鸟其实是不会飞的,但是他跑起来却很快,那么有人就会简单的覆盖掉基类的(Fly)方法,并不给出实现,而另外添加一个跑(Run)方法。 这样其实是不好的,当然我并不是让大家对以后的事做出预计,我想说的是,在发现父类与子类在某个方法发生冲突的时候,我们应该从源头抓起,我认为一个更好的方案是: 把基类TBird中的Fly方法改为DoAction(动作)方法,并指定为抽象方法,然后添加两个派生类TFlyBird(飞行的鸟)和TRunBird(跑步的鸟)。 在TFlyBird类中覆盖DoAction方法实现“飞翔”的动作,并添加public方法Fly,在Fly中调用DoAction来实现“飞翔”这一方法; 在TRunBird类中覆盖DoAction方法实现“跑步”的动作,并添加public方法Run,在Run中调用DoAction来实现“跑步”这一方法。 然后更改TGull等具有Fly方法(即飞行的鸟)的父类为TFlyBird,更改TOstrich等不具有Fly(即跑步的鸟)的父类为TRunBird。 那么,就算哪天我们又发现了一种会游泳的鸟,那么也只需要为TBird类派生一个TSwimBird(游泳的鸟)子类,并添加一个公有方法Swim让其调用DoAction来实现“游泳”的方法就可以了。 当然,我的方法并不是最好的,但是我认为,比直接在派生类中处理要好些。