Java 深入学习(18) —— 复用类
1 组合
组合是在新类中使用现有类的对象,也就是设计类的时候把要组合的类的对象加入到该类中作为自己的成员变量。组合是has_a
的关系。
-
组合的优点:
①:当前对象只能通过所包含的那个对象去调用其方法,所以所包含的对象的内部细节对当前对象时不可见的。
②:当前对象与包含的对象是一个低耦合关系,如果修改包含对象的类中代码不需要修改当前对象类的代码。
③:当前对象可以在运行时动态的绑定所包含的对象。可以通过set方法给所包含对象赋值。
组合的缺点:
①:容易产生过多的对象。
②:为了能组合多个对象,必须仔细对接口进行定义。
组合比继承更具灵活性和稳定性,所以在设计的时候优先使用组合。
2 继承
继承按现有类创建一个对象,不改变现有类,采用现有类的形式向其中添加新代码;(编译器强制你去初始化基类,是is_a
的关系,比如说Student继承Person,则说明Student is a Person。
继承的优点是子类可以重写父类的方法来方便地实现对父类的扩展。
-
继承的缺点有以下几点:
①:父类的内部细节对子类是可见的。
②:子类从父类继承的方法在编译时就确定下来了,所以无法在运行期间改变从父类继承的方法的行为。
③:如果对父类的方法做了修改的话(比如增加了一个参数),则子类的方法必须做出相应的修改。所以说子类与父类是一种高耦合,违背了面向对象思想。
2.1 初始化基类
从外部来看,子类就像是一个与基类具有相同接口的新类,或许还会有一些额外的方法和域。但继承并不只是复制基类的接口。当创了一个子类的对象时,该对象包含了一个基类的子对象,这个子对象与直接用基类创建的对象是相同的。
Java 会自动在子类的构造器中插入对基类构造器的调用。
构建过程是从基类“向外”扩散的,所以基类在到处类构造器可以访问它之前,就已经完成了初始化。
带参数的构造器
如果没有默认的基类构造器,或者想调用一个带参数的基类构造器,就必须用关键字 super 显示地编写调用基类构造器的语句,并且配以适当的参数列表:
注意:调用基类构造器必须是在子类构造器中要做的第一件事。
正确的写法:
输出:
只有当下列条件满足时才考虑使用继承:
- 子类是一种特殊的类型,而不只是父类的一个角色
- 子类的实例不需要变成另一个类的对象
- 子类扩展,而不是覆盖或者使父类的功能失效
3 代理
代理是继承和组合的中庸之道。将一个成员对象置于要构造的类中(就像组合),与此同时在新类中暴露了该类成员所有的方法(就像继承)。
(组合+继承)Java中没有直接的支持代理,(将基类对象作为代理类的成员,而代理类有对应于基类的所有方法,各方法内使用基类对象成员调用基类的方法。)
4 组合与继承之间的选择
- 组合 通常用于想在新类中使用现有类的功能而非它的接口,即, 在新类中嵌入的某个对象,让其实现所需要的功能,但新类的用户看到的只是为新类所定义的接口,而非所嵌入对象的接口
- 继承 使用某个现有类,并开发一个它的特殊版本。通常,这意味着你在使用一个通用类,并为了某种特殊需要而将其特殊化
- 如果必须向上转型,则继承是必要的
5 初始化及类的加载
Java 中的所有事物都是对象。
每个类的编译代码都存在于它自己的独立的文件中。该文件只在需要使用程序代码时,才会被加载。
“类的代码在初次使用时才加载”这通常是指加载发生于创建类的第一个对象的时候,但是当访问 static 域或者是 static 方法的时候,也会发生加载。
6 Reference
1、《Java编程思想》第7章复用类