第五天。
复用类(当然是为了做到代码重用)一般有两种方法:组合与继承。
其中组合是将对象引用置于新类中,继承即用extends关键字实现,而介于组合与继承之间还有一种关系称为代理。Java不直接支持代理,但是如JetBrains Idea IDE 等开发工具可以做到。代理时不继承旧类,而是先组合,再重新定义旧类中有用的方法,并在方法体中用所组合的类的对象调用相应方法。这样既得到了旧类中有用功能,又不至于旧类中的所有方法都暴露。
一般而言,is-a关系是用继承表达的,has-a关系是用组合来表达的。有一个最清晰的判断该使用继承还是组合的方法是——如果必须向上转型,则继承是必要的,否则可以使用组合。
尽管面向对象编程对继承极力强调,但在开始一个设计时,一般优先使用组合(或者可能是代理),只在确实必要时才使用继承。因为组合更具灵活性。
对于多态,它的缺陷是:对private方法、域及静态方法不适用。
多态还会在构造器内部出现问题:
当基类的构造器中调用了被导出类覆盖的方法时,由于此时导出类的构造器还未调用,导出类的成员也未初始化,故而会出现读取到脏数据而不是我们所想的样子。因此编写构造器有一条有效的准则:“用尽可能简单的方法使对象进入正常状态;如果可以的话,避免调用其他方法。“在构造器内唯一能够安全调用的那些方法是基类的final方法(也适用于private方法),因为这些方法不能够被覆盖,也就不会出现上述情况。当然这个在C++中不会出现,因为C++不是执行后期绑定。
最后,当你设计一个系统时,应该认识到程序开发是一种增量过程,犹如人类的学习一样,这一点很重要,程序开发依赖于实验,你可以尽己所能去分析,但当你开始执行一个项目时,你仍然无法知道所有的答案。如果将项目视作是一种有机的、进化着的生命体而去培养,而不是打算像盖摩天大楼一样快速见效,就会获得更多的成功和更迅速的回馈。继承与组合正式在面向对象程序设计中使得你可以执行这种实验的最基本的两个工具。