将公共操作和域放在超类
比如将姓名域放在 Person 类中,而不要放在 Employee 和 Student 中的原因。
不要使用受保护的域 (protected)
虽然子类可以直接访问父类中的 protected 域,但是 protected 机制并不能带来更好的保护。
- 第一,子类集合是无限制的,任何一个人都能够由某个类派生一个子类,并编写代码以直接访问 protected 的实例域,从而破坏了封装性。
- 第二,在 Java 程序设计语言中,在同一个包中的所有类都可以访问 proteced 域,而不管它是否为这个类的子类。
使用继承实现
使用继承很容易达到节省代码的目的,但有时候也被人们滥用了。比如,有人将钟点工继承自雇员,但这是有问题的。钟点工与雇员之间不属于is-a
关系is-a
关系。钟点工不是特殊的雇员。除非所有继承的方法都有意义,否则不要使用继承
假设想编写一个 Holiday 类。毫无疑问,每个假日也是一日,并且一日可以用 Gregorian Calendar 类的实例表示,因此可以使用继承。 ``` class Holiday extends GregorianCalendar {…}
但是 GregorianCalendar 类中有一个共有方法 `add()` 会将假日转换成非假日,所以这里使用继承不太合适。<br />可以继承 LocalDate ,就不会出现这个问题
### 在覆盖方法时,不要改变预期的行为
在覆盖一个方法的时候,不应该毫无原由地改变行为的内涵。<br />应该符合置换原则,原则上能用父类调用的方法,使用子类也没有问题。<br />但也会出现一些问题,置换原则要求 Manager.equals 不处理 bonus 域,因为 Employee.equals 没有它。实际上,凭空讨论这些问题毫无意义。关键在于,在覆盖子类中的方法时,不要偏离最初的设计想法。
### 使用多态,而非类型信息
如果你写出了这样的代码:
if (x is of type1) action1(x); else if (x is of type2) action2(x);
应该考虑使用多态性。将这个概念放在超类或接口中,就可以调用:
x.action();
``` 以便使用多态性提供的动态分派机制执行相应的动作。
不要过多地使用反射
反射机制使得人们可以通过在运行时查看域和方法,让人们编写出更具有通用性的程序。这种功能对于编写系统程序来说极其实用,但是通常不适于编写应用程序。反射是很脆弱的,即编译器很难帮助人们发现程序中的错误,因此只有在运行时才发现错误并导致异常。