03 抽象
1. 什么是抽象
- 抽象是指对于一个过程或者一件制品的某些细节有目的的隐藏
- 以便把其他方面、细节或者结构表达得更加清楚。(信息隐藏)
- 抽象,是控制复杂性最重要的工具
抽象示例:地图集
如果打开一本地图集,一般看到的常是一幅世界地图。该地图只显示了一些最主要的特征,如主要的山脉、海洋等等,但细节基本上都被忽略了。
随后的一系列地图将覆盖小一些的地理区域,也能处理更多的细节。例如,一块大陆(如各大洲)的地图将包括国家的边界和主要的国家。更小的区域(如国家)地图,将包括城市、各山峰的名称。一个城市的地图可能会包括进该城市的主要道路,再小一些的地图甚至还会画出一些建筑物。
2. 抽象技术
- 每个抽象层次,包括了某些信息,也忽略了某些信息。
- 人们通常使用一些简单的工具来建立、理解和管理复杂的系统。其中最重要的技术称为“抽象”(abstraction)。
3. 抽象层次
- 在典型的OOP程序中,有许多级抽象。
- 更高层次的抽象部分地体现了面向对象程序面向对象的特征。
4. 抽象层次 1-团体
在最高级别上,程序被视为一个对象的“团体”,这些对象间相互作用,以完成共同的目标。
- 在面向对象程序开发过程中,关于“团体”有两个层次的含义:
- 首先是指程序员的团体,他们在现实世界中相互作用,以便开发出应用程序来。
- 第二个团体是这些程序员创建的对象的团体,它们在虚拟世界中相互作用,以完成它们的共同目标。
- 信息隐藏和抽象均适用。
5. 抽象层次 2-单元
- 许多语言允许协同工作的对象组合到一个“单元”(unit)中。
例如,Java的“包” (packages),C++的“名字空间”(name spaces),Delphi中的“单元”(units)。
- 继承了早期语言中模块的思想
- 这些单元允许某些特定的名称暴露在单元以外,而其他特征则隐藏在单元中。
Java中的可见性,public,private,protected
- public修饰类成员时,表明该成员可以通过该类的任意对象进行显式的调用
- private修饰类成员时,该成员只能在该类中调用,不可通过该类对象在外界(即非类定义区)进行显式的调用
- 当用protected修饰类成员时,该成员可被其所属类的子类以及与其所属类处于同一包中的其他类所访问
6. 抽象层次 3-CS
- 处理两个独立对象之间的交互。
- 两个对象间交互时涉及两层抽象:一个对象(服务者, server)向另一个对象(客户, client)提供服务,二者之间以通信来交互。
该级别抽象通常用接口来表示。定义行为,但不描述如何来实现。
7. 抽象层次 4-服务实现方式
考虑抽象行为的具体实现方式。
例:多种实现堆栈方式。 顺序方式、链式方式……
8. 抽象层次 5-具体实现
- 方法的实现逻辑(具体过程或算法)
- 关注执行一个方法的具体操作实现。
9. 确定正确的抽象级别
抽象形式:
- 特殊化(特化分层、具体化、专门化)
- 分治法
- 不同视角
- 在软件开发的早期,关键的问题就是确定合适层次的抽象。
- 既不要忽略太多的细节,也不要包括太多的细节。
10. 抽象形式1:特化分层
- 又称为特殊化或具体化(specialization)
如,汽车是一个有轮的载运工具,而有轮的载运工具又是一个载运工具。 我们所了解的关于有轮的载运工具的知识,同样适用于汽车和自行车。
我们所了解的关于载运工具的知识,同样适用于马匹和自行车。
-
面向对象的语言,常常使用这种形式的抽象
-
一种处理复杂性的方式,是使用特殊化的层次来构建抽象。
-
有时这也称为分类法(taxonomy)
例如,生物分为动物和植物,动物又分为脊椎动物和无脊椎动物,脊椎动物包括哺乳动物,哺乳动物又分为猫、狗……等等
- 面向对象技术中,新的接口从现有的接口上形成。一个类从已有的类那里继承而来,这时,和原始类相关的所有特性(数据字段和行为)都同样适用于新类。
11. 抽象形式2:分治法
- 常用的一种抽象形式是将一层划分为多个组成部分。
例如,汽车是由发动机、传动机构、车身和车轮组成的。要理解汽车这个概念,只要依次检查其组成部件就行了。
- 这就是传统的分治法(divide and conquer)
抽象形式:分治法 – 目录 ( Catalogs )
- 当系统中组件数量变大时,常用目录(Catalogs)来进行组织。
- 日常生活中常用到不同类型的分类。例如电话号码簿、Internet搜索引擎等。
- 相似地,软件中也有很多分类目录。例如,类的列表、类中定义的方法的列表等。
- 为用户提供了一种机制,使用户可以从一个范围很大的集合中迅速地定位到某一特定的位置
分治法 - 服务视角
- 对接口和实现的划分,不仅从高层的角度对设计易于理解,而且使软件组件的替换成为可能。
- 接口描述软件组件所提供的服务,却不必描述完成服务所使用的技术,这个思想是理解和处理复杂软件系统的核心手段。
- 接口通过与完成抽象的实现相匹配来使系统正常工作。
- 发动机的设计者会与传动装置的接口相联系,而传动装置的设计者必须实现这些接口。
- 接口和实现的分离不但使在较高层次上理解一项设计更加容易(因为接口的描述比任何特定实现的描述都要简单得多)
- 而且使软件组件的互换性成为可能(因为可以使用任何实现,只有它能够满足接口规范)
- 团体的每一个成员,都提供一种被团队的其他成员使用的服务。
- 没有一个成员,可以独立解决问题。只有共同、协调工作,才能完成整体任务。
抽象形式:组合(Composition)
- 组合,是另一个由简单部分构建复杂结构的有力技术。(复合)
- 其中心思想,是由少量简单的形式,根据一些组合规则,构建出新的形式。
- 主要原则是允许合并机制,在于既可对初始形式进行组合,也可以对新形式进行组合。
12. 抽象形式3:不同视角
- 另一种形式的抽象,是对同一件物品提供不同的视角。每一个视角会强调某一些细节而忽略其他细节,因此,对同一对象描述出不同的特性。
例如,机械师眼里的汽车和外行眼里的汽车,看法是很不一样的。
13. 继承方式
Is-a继承
代表类之间或类与接口的继承关系,比如猫是动物,狗也是动物,都继承了动物的共同特性,在用OO语言实现时,应将猫和狗定义成两种类,均继承动物类。
如果A is-a B,那么B是A的基类
Has-a组合
"Has-a"代表的是对象和他成员的从属关系,同一种类的对象,通过它们的属性的不同值来区别
如果A has-a B,B是A的组成部分
14. 抽象形式:模式
在我们遇到新问题时,大多数人都会查看已经解决过的老问题中,是否有与新问题相似的情况。以前的问题可以作为一个解决问题的模型,略做修改可能就能解决新问题了。这就是软件模式(pattern)的思想。
广泛应用于对象团体中成员之间的相互作用方式。
面向对象技术并非革命性的,是过程-模块-抽象数据类型-面向对象
-
过程将重复执行的任务或者只有轻微变化的任务的定义集中于一处,用来复用,而无需进行多次代码的复制。(部分信息隐藏)
-
模块:解决全局名称空间拥挤问题。
用来改善建立和管理名称集合及其相关数值的一种技术。
公有部分可以从模块外存取,而私有部分只能从模块内存取。类型、数据(变量)和过程可以在任何部分定义
模块提供了将名称空间划分成两个部分的能力。
公有部分可以在模块外存取,私有部分只能从模块内存取。
-
实例化
模块不允许实现实例化。
实例化是一种能够建立数据区域多份拷贝的能力。 -
抽象数据类型。
定义抽象,创建多个实例;
使用实例,知其所提供操作,不必知道如何实现。
抽象数据类型思想的重要进展是最终把接口的概念和实现的概念分离开来。 -
以服务为中心。
汇编语言和过程:功能为中心;
模块和ADT:数据为中心;(结构、表示、操纵)
面向对象:服务为中心。 -
消息、继承和多态。
ADT基础上增加的新思想。
15. 抽象
抽象内涵
- 去除掉对象中与主旨无关的次要部分,或是暂时不予考虑的部分
- 抽取出与研究工作有关的实质性的内容加以考察
软件开发方法中所使用的抽象类型:
(1)过程抽象
- 将整个系统功能划分为若干部分,强调功能完成的过程和步骤
- 面向过程的软件开发方法采用的就是这种抽象方法
- 使用过程抽象有利于控制、降低整个程序的复杂度
- 缺点:这种方法本身自由度较大,难于规范化和标准化,操作起来有一定难度,在质量上不易保证
(2)数据抽象
- 把系统中需要处理的数据和这些数据上的操作结合在一起
- 根据功能、性质、作用等因素抽象成不同的抽象数据类型
- 每个抽象数据类型既包含数据,也包含针对这些数据的授权操作
- 相对于过程抽象,更为严格、也更为合理
16. 关于抽象类
抽象类 abstract class
抽象类是不能被直接实例化的类,即它没有直接的实例。
- 对象是对问题域中某些事物的抽象;
- 类是对对象的一个抽象;
Java中有一种专供子类来继承的类,这个类就是抽象类。
- 抽象方法:只有方法说明,没有方法体的方法称为抽象方法。
- 抽象类通常包括一个或多个抽象方法,抽象类的子类必须实现其父类定义的每一个抽象方法,除非该子类也是抽象类。
定义抽象类是因为属于同一类的多个子类,在实现某些方法时,会采用不同的实现方式,这时就要采用不同的方法体来定义。
- Java可以创建抽象类,专门用来当做父类。抽象类类似“模板”的作用,其目的是要依据它的格式来修改并创建新的类。
- 抽象类的方法可分为两种,一种是一般的方法,另一种是以abstract关键字为开头的“抽象方法”。“抽象方法”并没有定义处理的方式,而是要保留给由抽象类派生出的新类来定义。
- 抽象类不能直接用来产生对象。
END