前言
众所周知多态是面向对象设计三大基本特征(数据抽象、继承、多态)十分重要的一环,本篇将记录一下自己在学习这一概念时所得到的一些想法。由于本人能力有限,本篇大量引用了《JAVA编程思想》里的描述。
什么是多态?
对于大部分人来说,对于什么是多态这个问题都有一定了解,因此这里我就以一个简单的例子简单介绍下:
例子源于《JAVA编程思想(第四版)》第八章的练习9(自己编写的代码可能存在不足)
public class Rodent { //基类 “啮齿动物”
void run() { System.out.println("Rodent run"); }
void eat() { System.out.println("Rodent eat"); }
String what() { return "Rodent"; }
}
class Mouse extends Rodent { //继承 “啮齿动物” 的 “老鼠”
void run() { System.out.println("Mouse run"); }
void eat() { System.out.println("Mouse eat"); }
String what() { return "Mouse"; }
}
class Gerbil extends Rodent { //继承 “啮齿动物” 的 “鼹鼠”
void run() { System.out.println("Gerbil run"); }
void eat() { System.out.println("Gerbil eat"); }
String what() { return "Gerbil"; }
}
class Hamster extends Rodent { //继承 “啮齿动物” 的 “大颊鼠”
void run() { System.out.println("Hamster run"); }
void eat() { System.out.println("Hamster eat"); }
String what() { return "Hamster"; }
}
在我们创建对象并调用方法的时候:
public class test{
public static void main(String[] args) {
Rodent mouse = new Mouse();
Rodent gerbil = new Gerbil();
Rodent hamster = new Hamster();
mouse.eat();
gerbil.eat();
hamster.eat();
}
}
运行结果:
Mouse eat
Gerbil eat
Hamster eat
由于我们在每个子类(Mouse、Gerbil、Hamster)里都覆盖了基类的方法(eat、run、what)加上通过动态绑定,所以我们能“实现”不同动物的具体动作。
为什么需要多态
上面的例子我相信很多人都看过非常多类似的版本,包括我也是。但当我理解了这个例子后,并没有很好的理解到多态的意义。现在我们来读一下《JAVA编程思想》中的一句原话:多态是一项让程序员“将改变的事物与未变的事物分离开来”的重要技术。
现在我们来感受下这个“分离”的过程
我们现在改变下创建和调用方法的方式
public class test{
public static void animalRun(Rodent i) {
i.run();
}
public static void allAnimalRun(Rodent[] r) {
for(Rodent i : r)
animalRun(i);
}
public static void main(String[] args) {
Rodent [] rodents = {
new Mouse(),
new Gerbil(),
new Hamster()
};
allAnimalRun(rodents);
}
}
运行结果
Mouse run
Gerbil run
Hamster run
在这个例子里我们新添加了 animalRun 和 allAnimalRun 两个方法去“操作”我们的“动物”。其中animalRun针对的是个体,allAnimalRun针对的是群体,这两个方法就是所谓的“未变的事物”。可以看出,这两个新的方法可以完全忽略周围的代码,无论其他代码怎么改变,它仍然能够正常运行。这就是我们所需要的多态特性:我们所做出的代码修改,不会对程序中其他不应受到影响的部分产生破坏。
同时,这两个新添加的方法的设计模型体现了程序设计里的可扩展性。我们可以通过继承基类来得到新的类,从而增加新的功能。而那些操纵基类接口的方法不需要任何改动就可以应用于新类。