11.3.2 上移函数到父类
在面向对象开发过程中,继承是我们复用、设计代码的重要手段。然而继承体系中也是容易滋生代码重复的地方,尤其是对整个类族不是特别熟悉时,子类A要实现功能A,但是实际上父类中却含有该功能函数,子类B同时也需要该功能,也不知道其他类型中含有这样的功能。这就导致了同一个功能函数分布在不同的类型中,使得严重的代码重复。而当这个功能函数要修改以应对需求变更时,那么你很可能只修改了其中一个类中的函数,而分散在其他类功能相等的函数却未做处理,这就容易引发Bug。
如果某个函数在多个子类中都有相同的实现,这就是将该函数上移到父类中的适用场景。将相同功能的函数提到父类中,使得多个子类同时运用一份代码,减少代码重复率、出错率。如果并不是所有的子类都需要这个功能函数,那么你可能需要考虑为这些需要该功能函数的子类创建一个共同的父类,然后将该函数移到这个共同的父类中。
实现上移函数很简单,就是将多个子类的功能函数提取到父类中。因此,我们首先要在父类中新建一个功能函数,并且将子类中的功能代码复制到父类的函数中。如果多个子类的功能函数有差异,那么你需要根据差异来简单修改函数的参数列表以及实现,以使得它符合多个子类的需求,如果差异较大,那么可以使特定的子类覆写该函数。
我们看一个交通工具的例子,抽象类Vehicle中有启动、停止、加速、减速、打开车门、关闭车门的功能函数,代码如下:
publicabstractclassVehicle{ publicvoidstart(){ System.out.println("启动车子"); } publicvoidstop(){ System.out.println("停车"); } publicvoidspeedup(){ System.out.println("加速"); } publicvoidspeedDown(){ System.out.println("减速"); } publicvoidopenDoor(){ System.out.println("打开车窗吹吹风"); } publicvoidcloseDoor(){ System.out.println("关闭车门"); } } |
我们新建一个奥迪车的具体实现类,该类继承自Vehicle,然后我们发现Vehicle类居然没有实现转弯的功能函数,我们的奥迪车必须要有这个功能函数的,因此我们的奥迪车实现类如下所示:
public class Audi extends Vehicle {
public void turn() {
System.out.println("转弯");
}
// 其他功能
}
随着业务的扩展,我们需要往交通工具类族中添加宝马车的类型。但是,此时写宝马类的开发人员可能已经不是写Vehicle和Audi类的人,他对于这个类族并不是那么了解,经验也不是那么丰富,但是,他也发现要添加转弯功能,因此他的解决方案就是直接在宝马车类型中添加这个函数。实现如下:
public class BWM extends Vehicle {
public void turn() {
System.out.println("转弯");
}
// 其他功能
}
这样,交通工具类族中就有了两份同样的代码,而它们都是属于同一个类族中。此时,我们就可以通过上移函数的手法将重复的代码处理掉。首先我们在Vehicle中添加turn函数,然后将Audi和BMW中的turn函数去掉,代码如下:
public abstract class Vehicle { // 其他代码 public void turn() { System.out.println("转弯"); } } public class Audi extends Vehicle { // 其他功能函数 } public class BMW extends Vehicle { // 其他功能函数 } |
通过上移函数,我们就可以复用父类的turn函数。当turn函数需要进行修改时,我们也只需要修改父类中的实现即可。而不需要到不同的类中进行修改,如果出现需要到多个类修改功能一致的代码,那么也是需要重构的信号。
很多时候,是否需要上移代码并不是那么容易被发现,类族中的代码较多时,如果你对它们并不是很了解,那么你可能无法发现那些重复的代码,从而导致重复的代码越来越多。也不是所有的公用函数都应该放到最顶层的父类中,有的情况是你需要在现有的父类和子类之间再建立一个类,使得它作为中间层,并且把相应的功能函数移到新建的类中,而这个类则作为含有这个共同功能的基类,这样避免这个功能函数影响类族的所有类型,如果父类中含有了子类不需要的函数,那么就需要运用下移函数到子类的手法。
版权声明:51Testing软件测试网获人民邮电出版社和作者授权连载本书部分章节。
任何个人或单位未获得明确的书面许可,不得对本文内容复制、转载或进行镜像,否则将追究法律责任。