1.面向对象的核心概念
从理论上说,面向对象技术拥有四大基本特性。
(1)封装
这是一种隐藏信息的特征。封装这一特性不仅大大提高了代码的易用性,而且还使得类的开发者可以方便的更换新的算法,这种变化不会影响使用类的外部代码。可以用以下公式展示类的封装特性:
封装的类=数据+对此数据所进行的操作(即算法)
通俗的说,封装就是:包起外界不必需要知道的东西,只向外界展露可供展示的东西。
在面向对象理论中,封装这个概念拥有更为宽广的含义。小到一个简单的数据结构,大到一个完整的软件子系统,静态的如某软件系统要收集数据信息项,动态的如某个工作处理流程,都可以封装到一个类中。
具备这种“封装”的意见,是掌握面向对象分析与设计技巧的关键。
(2)抽象
讲到抽象,不得不涉及到现代科学技术的基础——数学。
数学是一门抽象的科学,面对着纷繁复杂的世间万物,数学不理会各种事物的独特特性,而只抽取它们在数量上的特性,深刻揭示了“世间万物”在数量上表现出的共同规律,抽象正是数学的本质特征。
数学的一个分支——离散数学是计算机科学的根基之一,因此,计算机科学从诞生之日起,就与数学有着密不可分的联系,抽象思维也是计算机科学的主要思维方法之一。
在使用面向对象的方法设计一个软件系统时,首先就要区分出现实世界中的事物所属的类型,分析它们拥有哪些性质与功能,再将它们抽象为在计算机虚拟世界中才有意义的实体——类,在程序运行时,由类创建出对象,用对象之间的相互合作关系来模拟真实世界中事物的相互关联。
在从真实世界到计算机虚拟世界的转换过程中,抽象起了关键的作用。
(3)继承
真实世界中,事物之间有着一种派生关系,比如“食品”这一大类中包括“水果”这一子类,而“苹果”又包含在“水果”这一子类中。用图形表示:
食品
↙ ↘
水果 蔬菜
↙ ↘ ↘
苹果 香蕉 土豆
在计算机世界中,以面向对象的观点不仅将上述事物抽象为类,而且将事物之间的派生关系也一并模拟出来,这种关系成为“继承”:
Food
↗ ↖
Fruit Vegetable
↗ ↖ ↖
Apple Banana Patato
在面向对象软件系统中,继承除了模拟现实世界中事物关系这一作用,还是一个“重用已有代码而又不破坏已有代码”的方法。举例来说:
现在要开发一个B项目,架构设计师发现以前完成的A项目中有部分类完全可以在B项目中重用,但需要增强这些类的功能以便适用于B项目。如果从A项目中直接抽取这些类的源代码并加以修改,虽然可以满足B项目的需要,但现在却需要维护两套功能类似的类代码,加大了管理的成本。在这种情况下,选择从A项目的类中用继承的方法派生出新类用在B项目中是一个可选的方案,既满足了新项目的需要,又避免了大量的重复代码与双倍的代码维护成本。
(4)多态
在现实生活中,我们常说:苹果是一种水果。苹果与水果这两个概念之间其实是一种特性与共性的关系,简称为IS_A关系,其特点为:水果拥有的特性,苹果一定有。
在前面的小节中我们用继承模拟了IS_A关系,“水果(Fruit)”是基类,“苹果(Apple)”是子类,IS_A关系可以用另一种方式来表达——基类拥有的特性,子类一定有。因此,可以把子类看成是一种“特殊”的基类。
举个例子:“给张三一个苹果”和“给张三一串香蕉”,虽然是两件不同的事,却可以统一说成“给张三一个水果”。
用“给张三一个水果”来指代“给张三一个苹果”和“给张三一串香蕉”,虽然在语义上比较“模糊”,但其适用性更广了,除了“苹果”和“香蕉”,以后还可以是“梨子”、“西瓜”、“葡萄”……,都可以用“给张三一个水果”来代表。
这种用一个比较抽象的事物来取代具体的事物的表达方法,在面向对象软件中用“多态”这一特性来模拟。
在编程时应用多态的方法,可以用一句话来表示:
用抽象的类编程。 注:这里,我们将“接口”也看成是一种特殊的抽象类,抽象类中可以有非抽象方法,而接口中所有方法都是抽象方法。
即在代码中本应使用某一具体子类的地方使用较为抽象的基类对象,这种方法所带来的好处是多态的代码具有“变色龙”的特性,即在不同的条件下,同样代码可以完成不同的功能。
适当地在开发中应用多态特性,可以开发出可扩充性很强的系统。
(5)小结
面向对象的四大特征不是彼此独立的,“抽象”和“封装”更多地体现为一种思维方法,主要体现在面向对象系统的总体分析和设计中,“继承”和“多态”则多应用于具体子系统和软件模块的设计与编码过程中,而且“继承”是“多态”的基础。