复用类
1. 复用类的两种主要方式:
- 第一种方法非常直观:只需在新的类中产生现有类的对象。由于新的类是由现有类的对象所组成,所以这种方法称为组合。该方法只是复用了现有程序代码的功能,而非它的形式。
- 第二种方法则更细致一些,它按照现有类的类型来创建新类。无需改变现有类的形式,采用现有类的形式并在其中添加新代码。这种神奇的方式称为继承,而且编译器可以完成其中大部分工作。
- 当然还有第三种方式,这种方式被称为代理,不过Java并没有提供对它的支持。这是继承与组合之间的中庸之道。使用代理可以拥有更多的控制力,我们可以选择只提供在成员对象中的方法的某个子集。
2. 初始化基类:
如果父类只含有一个不带参数的构造器(编译器会把它当成默认构造器),编译器会自动调用该父类的无参构造器。如果没有默认的基类构造器,或者想调用一个带参数的基类构造器,就必须用关键字super显式地编写调用基类构造器的语句,并且配以适当的参数列表。
3. 在组合与继承之间选择:
组合和继承都允许在新类中放置子对象,组合式显式地这样做,而继承则是隐式地做(子类创建一个对象,则该对象也包括了父类的一个对象)。
组合技术通常用于想在新类中使用现有类的功能而非它的接口这种情形。即,在新类中嵌入某个对象,让其实现所需的功能,但新类的用户看到的只是为新类所定义的接口,而非所嵌入对象的接口。为取得此效果,需要在新类中嵌入一个现有类的private对象。有时,允许类的用户直接访问新类中的组合成分是极具意义的;也就是说,将成员对象声明为public。如果成员对象自身都隐藏了具体实现,那么这种做法是安全的。
在继承的时候,使用某个现有类,并开发一个它的特殊版本。通常,这意味着你在使用一个通用类,并为了某种特殊需要而将其特殊化。略微思考一下就会发现,用一个“交通工具”对象来构成一部“车子”是毫无意义的,因为“车子”并不包含“交通工具”,它仅是一种交通工具(is-a关系)。“is-a”(是一个)的关系是用继承来表达的,而“has-a”(有一个)的关系是用组合来表达的。
在面向对象编程中,生成和使用程序代码最有可能采用的方法就是直接将数据和方法包装进一个类中,并使用该类的对象。也可以运用组合技术使用现有类来开发新的类;而继承技术其实是不太常用的。因此,尽管在教授OOP的过程中虽然多次强调继承,但这并不意味着尽可能使用它。相反,应当慎用这样技术,其使用场合仅限于你确信使用该技术确实有效的情况。到底是该用组合还是用继承,一个最清晰的判断办法就是问一问自己是否需要从新类向基类进行向上转型。如果必须向上转型,则继承是必要的;但如果不需要,则应当好好考虑自己是否需要继承。所以,在开始一个设计时,一般优先选择使用组合(或者可能使用代理),只在确实必要时才使用继承。