继承的设计技巧

版权声明:本文为博主原创文章,转载附上地址就可以啦,多交流,一起进步。 https://blog.csdn.net/weixin_30363263/article/details/84314985

继承的设计技巧

摘自《java核心技术》第五章继承设计技巧


1. 将公共操作和域放在超类
这就是为什么将姓名域放在 Person 类中, 而没有将它放在 Employee 和 Student 类中的原因。

2. 不要使用受保护的域
有些程序员认为, 将大多数的实例域定义为 protected 是一个不错的主意,只有这样,子类才能够在需要的时候直接访问它们。然而, protected 机制并不能够带来更好的保护, 其原因主要有两点:

  1. 子类集合是无限制的, 任何一个人都能够由某个类派生一个子类, 并编写代码以直接访问 protected 的实例域,从而破坏了封装性。
  2. 在 Java 程序设计语言中, 在同一个包中的所有类都可以访问 proteced 域, 而不管它是否为这个类的子类。

不过, protected 方法对于指示那些不提供一般用途而应在子类中重新定义的方法很有用。

3.使用继承实现“ is-a”关系

使用继承很容易达到节省代码的目的,但有时候也被人们滥用了。例如, 假设需要定义一个钟点工类。 钟点工的信息包含姓名和雇佣日期, 但是没有薪水。 他们按小时计薪, 并且不会因为拖延时间而获得加薪。这似乎在诱导人们由 Employee 派生出子类 Contractor, 然后 再增加一个 hourlyWage 域。

public class Contractor extends Employee {
    private double hourlyWage; 
}

这并不是一个好主意。 因为这样一来, 每个钟点工对象中都包含了薪水和计时工资这两个域。 在实现打印支票或税单方法耐候, 会带来诞的麻烦, 并且与不采用继承, 会多写很制戈码。

原因就在于:钟点工与雇员之间不属于“ is-a” 关系。钟点工不是特殊的雇员。


4. 除非所有继承的方法都有意义, 否则不要使用继承
假设想编写一个 Holiday 类毫无疑问, 每个假日也是一日, 并且一日可以用 GregorianCalendar 类的实例表示, 因此可以使用继承。

class Holiday extends CregorianCalendar { . . , }

很遗憾, 在继承的操作中, 假日集不是封闭的。 在 GregorianCalendar 中有一个公有方法 add, 可以将假日转换成非假日:

Holiday Christmas; Christmas.add(Calendar.DAY_OF_MONTH, 12);

因此, 继承对于这个例子来说并不太适宜。
需要指出, 如果扩展 LocalDate 就不会出现这个问题。 由于这个类是不可变的, 所以没有任何方法会把假日变成非假日。

5. 在覆盖方法时, 不要改变预期的行为
置换原则不仅应用于语法, 而且也可以应用于行为,这似乎更加重要。 在覆盖一个方法的时候, 不应该毫无原由地改变行为的内涵。就这一点而言, 编译器不会提供任何帮助, 即编译器不会检查重新定义的方法是否有意义。

例如,可以重定义Holiday类中add方法“ 修正” 原方法的问题, 或什么也不做, 或抛出一个异常, 或继续到下一个假日。

然而这些都违反了置换原则。

6. 使用多态, 而非类型信息

无论什么时候, 对于下面这种形式的代码:

if (x is oftype1)

action(x);
else if (x is oftype2)

actioni(y); 

都应该考虑使用多态性。

使用多态方法或接口编写的代码比使用对多种类型进行检测的代码更加易于维护和扩展。

7. 不要过多地使用反射
反射机制使得人们可以通过在运行时查看域和方法, 让人们编写出更具有通用性的程序。

这种功能对于编写系统程序来说极其实用, 但是通常不适于编写应用程序。

反射是很脆弱的, 即编译器很难帮助人们发现程序中的错误, 因此只有在运行时才发现错误并导致异常。

猜你喜欢

转载自blog.csdn.net/weixin_30363263/article/details/84314985