就其本身来说对象的概念可为我们带来极大的便利它在概念上允许我们将各式各样数据和功能封装到一起这样便可恰当表达问题空间的概念不用刻意遵照基础机器的表达方式在程序设计语言中这些概念则反映为具体的数据类型(使用class关键字) 我们费尽心思做出一种数据类型后假如不得不又新建一种类型令其实现大致相同的功能那会是一件非常令人灰心的事情但若能利用现成的数据类型对其进行克隆再根据情况进行添加和修改情况就显得理想多了继承正是针对这个目标而设计的但继承并不完全等价于克隆在继承过程中若原始类(正式名称叫作基础类超类或父类)发生了变化修改过的克隆类(正式名称叫作继承类或者子类)也会反映出这种变化在Java语言中继承是通过extends关键字实现的 使用继承时相当于创建了一个新类这个新类不仅包含了现有类型的所有成员(尽管private成员被隐藏起来且不能访问)但更重要的是它复制了基础类的接口也就是说可向基础类的对象发送的所有消息亦可原样发给衍生类的对象根据可以发送的消息我们能知道类的类型这意味着衍生类具有与基础类相同的类型!为真正理解面向对象程序设计的含义首先必须认识到这种类型的等价关系 由于基础类和衍生类具有相同的接口所以那个接口必须进行特殊的设计也就是说对象接收到一条特定的消息后必须有一个方法能够执行若只是简单地继承一个类并不做其他任何事情来自基础类接口的方法就会直接照搬到衍生类这意味着衍生类的对象不仅有相同的类型也有同样的行为这一后果通常是我们不愿见到的 有两种做法可将新得的衍生类与原来的基础类区分开第一种做法十分简单为衍生类添加新函数(功能)这些新函数并非基础类接口的一部分进行这种处理时一般都是意识到基础类不能满足我们的要求所以需要添加更多的函数这是一种最简单最基本的继承用法大多数时候都可完美地解决我们的问题然而事先还是要仔细调查自己的基础类是否真的需要这些额外的函数 改善基础类 尽管extends关键字暗示着我们要为接口扩展新功能但实情并非肯定如此为区分我们的新类第二个办法是改变基础类一个现有函数的行为我们将其称作改善那个函数 为改善一个函数只需为衍生类的函数建立一个新定义即可我们的目标是尽管使用的函数接口未变但它的新版本具有不同的表现 等价与类似关系 针对继承可能会产生这样的一个争论继承只能改善原基础类的函数吗?若答案是肯定的则衍生类型就是与基础类完全相同的类型因为都拥有完全相同的接口这样造成的结果就是我们完全能够将衍生类的一个对象换成基础类的一个对象!可将其想象成一种纯替换在某种意义上这是进行继承的一种理想方式此时我们通常认为基础类和衍生类之间存在一种等价关系——因为我们可以理直气壮地说圆就是一种几何形状为了对继承进行测试一个办法就是看看自己是否能把它们套入这种等价关系中看看是否有意义 但在许多时候我们必须为衍生类型加入新的接口元素所以不仅扩展了接口也创建了一种新类型这种新类型仍可替换成基础类型但这种替换并不是完美的因为不可在基础类里访问新函数我们将其称作类似关系新类型拥有旧类型的接口但也包含了其他函数所以不能说它们是完全等价的举个例子来说让我们考虑一下制冷机的情况假定我们的房间连好了用于制冷的各种控制器也就是说我们已拥有必要的接口来控制制冷现在假设机器出了故障我们把它换成一台新型的冷热两用空调冬天和夏天均可使用冷热空调类似制冷机但能做更多的事情由于我们的房间只安装了控制制冷的设备所以它们只限于同新机器的制冷部分打交道新机器的接口已得到了扩展但现有的系统并不知道除原始接口以外的任何东西 认识了等价与类似的区别后再进行替换时就会有把握得多尽管大多数时候纯替换已经足够但您会发现在某些情况下仍然有明显的理由需要在衍生类的基础上增添新功能通过前面对这两种情况的讨论相信大家已心中有数该如何做 |