多态的含义:同一操作作用于不同的对象上面,可以产生不同的解释和不同的执行结果,换句话说,给不同的对象发送同一个消息的时候,这些对象会根据这个消息分别给出不同的反馈。
多态背后的思想是将“做什么”和“谁去做以及怎样去做”分离开来,也就是将“不变的事物”与“可能改变的事物”分离开来。
一段多态的Javascript代码,例如:
var makeSound = function(animal) { // 把不变的部分隔离出来
animal.sound();
};
把可变的部分各自封装起来,每个类型的动物各自封装
var Duck = function() {};
Duck.prototype.sound = function() {
console.log("嘎嘎嘎");
};
var Chicken = function() {};
Chicken.prototype.sound = function() {
console.log("咯咯咯");
};
makeSound( new Duck() ); // 嘎嘎嘎
makeSound( new Chicken() ); // 咯咯咯
使用继承得到多态效果:
继承通常包括实现继承和接口继承,下面介绍的案例是实现继承
我们先创建一个Animal抽象类,再分别让Duck和Chicken都继承自Animal抽象类:
public abstract class Animal {
abatract void makeSound(); // 抽象方法
};
public class Chicken extends Animal {
public void makeSound() {
System.out.println("咯咯咯");
}
};
public class Duck extends Animal {
public void makeSound() {
System.out.println("嘎嘎嘎");
}
};
Animal duck = new Duck();
Animal chicken = new Chicken();
现在剩下的就是让AnimalSound类的makeSound方法接受Animal类型的参数,而不是具体的Duck类型或者Chicken类型:
public class AnimalSound {
// 接受Animal类型的参数
public void makeSound( Animal animal) {
animal.makeSoud();
};
};
public class Test {
public static void main( String args[ ] ) {
AnimalSound animalSound = new AnimalSound ();
Animal duck = new Duck();
Animal chicken = new Chicken();
animalSound.makeSound( duck ); // 输出嘎嘎嘎
animalSound.makeSound( chicken ); // 输出咯咯咯
};
};
从前面的讲解我们得知,多态的思想实际上是把“做什么”和“谁去做”分离开来,要实现这一点,归根结底先要消除类型之间的耦合关系。如果类型之间的耦合关系没有被消除,那么我们在makeSound方法中指定了发出叫声的对象是某个类型,它就不可能再被替换为另外一个类型。
上面的例子中,某一种动物能否发出叫声,只取决于它有没有makeSound方法,而不取决于它是否是某种类型的对象,这里不存在任何程度上的“类型耦合”。
多态在面向对象程序设计中的作用:
多态最根本的作用就是通过把过程化的条件分支语句转化为对象的多态性,从而消除这些条件分支语句。将行为分布在各个对象中,并让这些对象各自负责自己的行为,这正是面向对象设计的优点。
案例2,编写一个地图应用,显示地图
var googleMap = {
show : function() {
console.log("开始渲染谷歌地图");
};
}
var baiduMap = {
show : function() {
console.log("开始渲染百度地图");
};
};
var renderMap = function(type) {
if ( type === "google") {
googleMap.show();
} else if (type === "baidu") {
baiduMap.show();
};
};
把程序中相同的部分抽象出来,那就是显示某个地图:
var renderMap = functioin(map) {
if (map.show instanceof Function) {
map.show();
};
};
renderMap( googleMap ); // 输出开始渲染谷歌地图
renderMap( baiduMap ); // 输出开始渲染百度地图
在JavaScript这种将函数作为一等对象的语言中,函数本身也是对象,函数用来封装行为并且能够被四处传递。当我们对一些函数发出“调用”的消息时,这些函数会返回不同的执行结果,这是“多态性”的一种体现,也是很多设计模式在JavaScript中可以用高阶函数来代替实现的原因。