面向对象的特征
面向对象的特征主要可以概括为封装性、继承性和多态性,下面我们进行简要介绍。
1. 封装性
封装指的是隐藏内部的实现细节,只对外开放操作接口。接口就是对象的方法,无论对象的内部多么复杂,用户只需知道这些接口怎么使用即可。例如,计算机是非常高精密的电子设备,其实现原理也非常复杂,而用户在使用时并不需要知道这些细节,只要会操作键盘和鼠标就可以使用了。
封装的优势在于,无论一个对象内部的代码经过了多少次修改,只要不改变接口,就不会影响到使用这个对象时编写的代码。正如电脑上的USB接口,不论如何更换,只要接口兼容,用户可以随意更换鼠标。
2. 继承性
继承是指一个对象继承另一个对象的成员,从而在不改变另一个对象的前提下进行扩展。例如,猫和狗都属于动物,程序中便可以描述猫和狗继承自动物。同理,波斯猫和巴厘猫都继承自猫,沙皮狗和斑点狗都继承自狗。它们之间的继承关系如图1所示。
图1 动物继承关系图
由图1可知,从波斯猫到猫科,再到动物,是一个逐渐抽象的过程,可以使对象的层次结构清晰。例如,当指挥所有的猫捉老鼠时,波斯猫和巴厘猫会听从命令,而犬科动物不受影响。
在开发中,利用继承一方面可以在保持接口兼容的前提下对功能进行扩展,另一方面增强了代码的复用性,为程序的修改和补充提供便利。
3. 多态性
多态指的是同一个操作作用于不同的对象,会产生不同的执行结果。实际上JavaScript被设计成一种弱类型语言(即一个变量可以存储任意类型的数据),就是多态性的体现。例如,数字、数组、函数都具有toString()方法,当使用不同的对象调用该方法时,执行结果不同,示例代码如下。
var obj = 123;
console.log(obj.toString()); // 输出结果:123
obj = [1, 2, 3];
console.log(obj.toString()); // 输出结果:1,2,3
obj = function() {};
console.log(obj.toString()); // 输出结果:function () {}
在面向对象中,多态性的实现往往离不开继承,这是因为继承可以让所有的同类对象拥有相同的方法,然后每个对象可以再根据自己的特点来改变同名方法的执行结果。
虽然面向对象提供了封装、继承、多态这些设计思想,但并不表示只要满足这些特征就可以设计出优秀的程序,开发人员还需要考虑如何合理地运用这些特征。例如,在封装时,如何给外部调用者提供完整且最小的接口,使外部调用者可以顺利得到想要的功能,不需要研究其内部的细节;在进行继承和多态设计时,如何为同类对象设计一套相同的方法进行操作等。