2.1 面向对象

2.1 面向对象

在目前的软件开发领域有两种主流的开发方法:结构化开发方法面向对象开发方法

早期的编程语言如C、BasicPascal等都是结构化编程语言;

随着软件开发技术的逐渐发展,人们发现面向对象可以提供更好的可重用性、可扩展性和可维护性,于是催生了大量的面向对象的编程语言,如C++、Java、C#和Ruby等。

2.1.1 结构化程序设计简介

结构化程序设计方法主张功能来分析系统需求,其主要原则可概括为自顶向下、逐步求精、模块化等。

SA SD SP

结构化程序设计
首先采用结构化分析(Structured Analysis,SA)方法对系统进行需求分析,
然后使用结构化设计(Structured Design,SD)方法对系统进行概要设计详细设计,
最后采用结构化编程(Structured Program,SP)方法来实现系统。

使用这种SASDSP的方式可以较好地保证软件系统的开发进度和质量。

因为结构化程序设计方法主张按功能把软件系统逐步细分,因此这种方法也被称为面向功能的程序设计方法;结构化程序设计的每个功能都负责对数据进行一次处理,每个功能都接受一些数据,处理完后输出一些数据,这种处理方式也被称为面向数据流的处理方式

结构化程序设计的最小程序单元 函数

结构化程序设计里最小的程序单元是函数,每个函数都负责完成一个功能,用以接收一些输入数据,函数对这些输入数据进行处理,处理结束后输出一些数据。整个软件系统由一个个函数组成,其中作为程序入口的函数被称为主函数,主函数依次调用其他普通函数,普通函数之间依次调用,从而完成整个软件系统的功能。

自顶向下

结构化设计需要采用自顶向下的设计方式,在设计阶段就需要考虑每个模块应该分解成哪些子模块,每个子模块又分解成哪些更小的模块……依此类推,直至将模块细化成一个个函数。

每个函数都是具有输入、输出的子系统,函数的输入数据包括函数形参、全局变量和常量等,函数的输出数据包括函数返回值以及传出参数等。

结构化程序设计局限性

结构化程序设计方式有如下两个局限性。

  • 设计不够直观,与人类习惯思维不一致。采用结构化程序分析、设计时,开发者需要将客观世界模型分解成一个个功能,每个功能用以完成一定的数据处理。
  • 适应性差,可扩展性不强。由于结构化设计采用自顶向下的设计方式,所以当用户的需求发生改变,或需要修改现有的实现方式时,都需要自顶向下地修改模块结构,这种方式的维护成本相当高。

2.1.2 程序的三种基本结构

goto语句的问题

在过去的日子里,很多编程语言都提供了GOTO语句,GOTO语句非常灵活,可以让程序的控制流程任意流转——如果大量使用GOTO语句,程序完全不需要使用循环。但GOTO语句实在太随意了,如果程序随意使用GOTO语句,将会导致程序流程难以理解,并且容易出错。在实际软件开发过程中,更注重软件的可读性和可修改性,因此GOTO语句逐渐被抛弃了。

保留字goto

Java语言拒绝使用GOTO语句,但它将goto作为保留字,意思是目前Java版本还未使用GOTO语句,但也许在未来的日子里,当Java不得不使用GOTO语句时,Java还是可能使用GOTO语句的。

程序设计的三种基本结构

结构化程序设计非常强调实现某个功能的算法,而算法的实现过程是由一系列操作组成的,这些操作之间的执行次序就是程序的控制结构。1996年,计算机科学家BohmJacopini证明了这样的事实:任何简单或复杂的算法都可以由顺序结构选择结构循环结构这三种基本结构组合而成。所以,这三种结构就被称为程序设计的三种基本结构,也是结构化程序设计必须采用的结构。

2.1.3 面向对象程序设计简介

面向对象程序设计的最小的程序单元是 类

采用面向对象方式开发的软件系统,其最小的程序单元是类,这些类可以生成系统中的多个对象,而这些对象则直接映像成客观世界的各种事物。

面向对象的软件系统由多个类组成,类代表了客观世界中具有某种特征的一类事物,这类事物往往有一些内部的状态数据,比如人有身高、体重、年龄、爱好等各种状态数据,当然程序没必要记录该事物所有的状态数据,程序只要记录业务关心的状态数据即可。

面向对象的语言不仅使用类来封装一类事物的内部状态数据,这种状态数据就对应于类的成员变量,而且类会提供操作这些状态数据的方法,还会为这类事物的行为特征提供相应的实现,这种实现也是方法。因此可以得到如下基本等式:

成员变量(状态数据) + 方法(行为) = 类定义

面向对象比面向过程编程粒度要大

从这个等式来看,面向对象比面向过程的编程粒度要大:面向对象的程序单位是类;而面向过程的程序单位是函数(相当于方法)。

2.1.4 面向对象的基本特征

面向对象的是三个基本特征 封装 继承 多态

面向对象方法具有三个基本特征:封装(Encapsulation)、继承(Inheritance)和多态(Polymorphism).

  • 封装指的是将对象的实现细节隐藏起来,然后通过一些公用方法来暴露该对象的功能;
  • 继承是面向对象实现软件复用的重要手段,当子类继承父类后,子类作为一种特殊的父类,将直接获得父类的属性和方法;
  • 多态指的是子类对象可以直接赋给父类变量,但运行时依然表现出子类的行为特征,这意味着同一个类型的对象在执行同一个方法时,可能表现出多种行为特征。

抽象

除此之外,抽象也是面向对象的重要部分,抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面。抽象并不打算了解全部问题,而只是考虑部分问题。例如,需要考察Person对象时,不可能在程序中把Person的所有细节都定义出来,通常只能定义Person的部分数据、部分行为特征——而这些数据、行为特征是软件系统所关心的部分。

虽然抽象是面向对象的重要部分,但抽象不是面向对象的特征之一,因为所有的编程语言都需要抽象。当开发者进行抽象时应该考虑哪些特征是软件系统所需要的,那么这些特征就应该使用程序记录并表现出来。因此,需要抽象哪些特征没有必然的规定,而是取决于软件系统的功能需求。

面向对象的其他特征

面向对象还支持如下几个功能。

  • 对象是面向对象方法中最基本的概念,它的基本特点有:标识唯一性、分类性、多态性、封装性、模块独立性好。
  • 类是具有共同属性、共同方法的一类事物。类是对象的抽象:对象则是类的实例。而类是整个软件系统最小的程序单元,类的封装性将各种信息细节隐藏起来,并通过公用方法来暴露该类对外所提供的功能,从而提高了类的内聚性,降低了对象之间的耦合性。
  • 对象间的这种相互合作需要一个机制协助进行,这样的机制称为“消息”。消息是一个实例与另个实例之间相互通信的机制。
  • 在面向对象方法中,类之间共享属性操作的机制称为继承。继承具有传递性。继承可分为单继承(一个继承只允许有一个直接父类,即类等级为树形结构)与多继承(一个类允许有多个直接父类)。

Java不支持多继承

由于多继承可能引起继承结构的混乱,而且会大大降低程序的可理解性,所以Java不支持多继承。

面向对象和基于对象的区别

判断一门语言是否是面向对象的,通常可以使用继承和多态来加以判断

  • 面向对象”和“基于对象”都实现了“封装”的概念,
  • 但是面向对象实现了“继承和多态”,
  • 而“基于对象”没有实现实现“继承和多态”。