《2022年第章面向对象的程序设计与软件开发初步 .pdf》由会员分享,可在线阅读,更多相关《2022年第章面向对象的程序设计与软件开发初步 .pdf(9页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第2章面向对象的程序设计与软件开发初步目标阅读和研究本章之后,你应该能够:说出面向对象的程序设计的基本组成部分。区分类和对象。区分类和实例方法。区分类和实例数据值。利用表示类、对象和面向对象程序设计的其他组成部分的图标画出对象框图。讲述面向对象的程序中继承性的重要意义。说出并解释软件生命周期的各个阶段。引言开始编写实际程序之前,我们需要介绍面向对象程序设计(Object Oriented Programming)的几个基本的概念,面向对象的程序设计是你将在本书学习的程序设计方式。本章的目的是让你留下面向对象的程序设计的印象,介绍有关面向对象的程序设计的概念基础。学习这本书之后,你可能需要重新阅
2、读本章。读者中也许有一部分人有一定的程序设计经验,无论是面向对象的或非面向对象的,大概均会感到C#与自己以前学过的程序设计语言有些相似之处。这种相似可以加快你的学习进程。 但在许多情况下,看起来很相似, 实际却完全不同,所以请你不要对相似之处草率地下结论。本章的另一个目的是介绍软件开发过程。为了能够编写程序,只是知道面向对象程序的组成是不够的, 你必须学习程序的开发过程。在这一章中。 我们将简要介绍软件的开发过程。2.1 类和对象面向对象的程序设计中两个最重要的概念是类和对象。从广义的术语来说,对象 (object) 是一个可以想象的物体,既是有形的又是无形的。以面向对象方式编写的程序由相互作
3、用的对象组成。 银行用来维护往来账户的程序可能有许多Account、 Customer、 Transaction 和 ATM 对象。 对象由数据和处理这些数据的操作组成。例如,一个 Account 对象可以由诸如账户号码、所有者、 开户日期、 最初余额以及当前余额这样的数据和诸如存款、转账以及取款这样的操作组成。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 1 页,共 9 页 - - - - - - - - - 图 2.1 对象的图形表示法几乎所有有价值的程序都有许多类型相同的对象
4、。例如,在银行使用的程序中我们可想象出它有许多Account 、 Customer 和其他的对象。 图 2 2 显示两个名为Jack 和 Jill 的 Customer对象和一个名为SV l29 的 Account 对象。图 2.2 名为 Jack 和 Jill 的两个 Customer 对象和一个名为Svl29 的 Account 对象我们在程序内部编写出指令创建对象。为了让计算机能够创建一个对象,我们必须提供一个称为 “类 (class)的定义。 类是计算机用来创建对象的模型或模板,对象称为 “类的实例(instance)。对象是某个确切类的实例,一个类的实例属于(belongs to)这
5、个类。 Jack 和 JilI这两个 customer 对象就是 customer 类的实例。只要一个类被定义,我们即可根据程序的需要创建这个类的许多对象。在创建一个类的实例(对象)之前必须定义这个类。图 2.3 所示为本书中用来表示类的框图,图 2.4 显示两个类和5 个对象。 注意,其中包括了对象的类名,以清楚地识别某对象属于哪个类。图 2.3 类的图形表示法名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 2 页,共 9 页 - - - - - - - - - 图 2.4 有两个
6、 Account 对象和 3 个 Customer对象的两个类Account 和 Customer 2.2 消息和方法编写面向对象的程序的过程中我们首先定义类,而当程序开始运行时,由这些类创建对象以完成任务。 任务可以是两个数相加、计算学校贷款利息支付以及计算航天飞机的返回角度等。为了命令类或对象执行一项任务,我们要为其发送一个消息(message)。例如,我们发送 new 消息给 Account 类以创建一个实例(一个 Account 对象),然后可以为Account 对象发送 deposit 消息,存款100 美元。处理消息的类或对象必需相应编程,不能只是将消息随便发送给一个类或对象,而只
7、能将消息发送给能够理解这个消息的类或对象。处理所收到消息的类或对象必须有对应的方法(method),也就是类或对象为完成一项任务而执行的指令序列。为类定义的方法称为“类方法_(class method) ,而为对象定义的方法就是实例方法(instance method)。我们首先看一个实例方法的例子。假设为Account 对象定义了deposit 方法,然后命令这个对象将指定数目的存款存入账户。由此方法定义,我们可以为Account对象发送一个deposit 消息,随后存入此存款。 我们传递给对象的数值称为“消息的变量 (argument) 。注意,发送给对象或类的消息名必须与该方法名相同。图
8、2.5 描述说明了消息的发送过程。图 2.5 发送 deposit 消息给 Account 对象图 2.5 所示的框图显示的是单向传送,即对象完成所请求的操作(存入指定的存款),但是不响应信息发送者。在很多情况下, 我们需要双向传送。在双向传送中,对象返回给信息发送者 一个 值。例 如, 假设 我们需 知道 一个 账户按 月收 取的 费用, 则可 以定 义一个getMonthlyFee 方法返回月费用。图2.6 所示为一个为信息发送者返回值的方法。一个方法名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - -
9、- - - - 第 3 页,共 9 页 - - - - - - - - - 还可以报告所请求操作的状态,而不一定返回数字值。例如,我们可以定义一个deduct 方法,如果减去所传递的数量之,后得出负数余额,则返回fail 状态。图 2.6 每月费用的结果返回给信息的发送者类似地, 如果类或对象不处理你发送的消息,则不能将消息发送给这个类或对象,即类或对象必须包含对应的方法。将消息发送给类或对象是执行对应方法的途径,如果没有对应的方法,就什么都不会发生(事实上,将发生错误)。现在我们查看一个类方法的例子,如图2.7 所示的类方法getAverageBalance 返回所有Account 对象的平
10、均余额。 诸如 getAverageBalance 这样的处理与类的实例有关的共同信息的方法通常被定义为类方法。因此为适合单独实例的任务定义实例方法,应为适合所有实例的任务定义类方法。图 2.7 类方法 getAverageBalance 返回所有 Account 对象的平均余额注意我们如何用不同的图标表示类方法(长方形 )和实例方法 (圆角长方形 )。由于类定义是我们定义其实例化所拥有方法之处,因此必须把类方法和实例方法都连接到类图标。虚线表示不能将实例消息发送给类本身。图2.8 概括了用来表示类、实例及其方法的绘制方法。名师资料总结 - - -精品资料欢迎下载 - - - - - - -
11、- - - - - - - - - - - 名师精心整理 - - - - - - - 第 4 页,共 9 页 - - - - - - - - - 图 2.8 类和对象的图形表示法2.3 类和实例数据值Account 对象的 deposit 方法命令这个对象将指定数量的存款存入当前余额,但是对象在何处保存当前余额?要知道对象由数据值和方法组成。与定义类和实例方法类似,我们需要定义类和实例数据值。举例来说, 我们为Account 对象定义一个实例数据值current balance,以保存当前余额。 图 2.9 显示 3 个 Account 对象及其数据值current balance。注意它们全
12、部有同样的数据值current balance。同一个类的所有实例化将拥有同一组数据值。current balance实际的美元数如框图所说明,各个实例不同。如同开户余额和账户编号这样的项是Account对象可能拥有的其他实例数据值。图 2.9 3个 Account 对象拥有同样的current balance,但实际的美元数不同类数据值用来表示所有实例共享的信息或表示与实例有关的共同信息。例如,如果每个账户必须维持一个最小余额,比如 100 美元, 则我们可以定义一个类数据值。一个实例可以访问其所属类的类数据值,因此每个Account 对象可以访问这个minimum balance 类数据值
13、。图 2.10 说明如何表示类数据值。为了理解类数据值的重要性,我们查看如果将最小余额表示为实例数据值将发生的情况。 图 2.11 显示 3 个 Account 对象, 其中 current balance 具有不同美元数, 但 minimum balance的美元数相同。很明显,minimum balance 的重复是多余的,而且浪费空间。考虑如果银行名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 5 页,共 9 页 - - - - - - - - - 将 minimum bala
14、nce 升到200 美元后发生的情况。如果有100 个 Account对象,那么minimumbalance 的所有 100 个副本都必须更新, 将 minimum balance 定义为类数据值即可避免这种情况。数据值有两种类型:可以随时改变的和不能改变的。前者称为“变量”(variable),后者为“常数” (constant)。注意,现在有4 种数据值:类变量、类常数、实例变量和实例常数。图 2.10 3 个 Account 对象共享以类数据值存储的信息(minimum balance=100 美元 ) 图 2.11 在实例化数据值中复制信息(minimum balance=100 美元
15、 )的 3 个 Account 对象2.4 继承当我们用Account, 类及其实例阐明面向对象的概念时,有些人可能正在考虑经常账户,而其他人可能已经考虑储蓄账户。在上面的例子中,我们未区分这两种账户。如果稍微认真地考虑这个问题,你将明白, 即使这两种账户有许多共同的特征,事实上它们也是不同的。一般来说, 用单个类作为两个或多个相似,但不同的实体模型不是好的设计。让我们研究竟为什么这种情况下使用Account 类。 假设银行要求对储蓄账户和经常账户保持不同的最小余额,那么我们如何用单个的类作为这种情况的模型?有两种选择:(1)令 minimum balance 为实例变量。(2)设 2 个类变
16、量minimum savings balance 和 minimum checking balance 。两种解决方法都有重要缺陷:第 1 种方法复制相同的值, 我们已经说过这是不好的设计;第 2 种方法使取款的处理变得复杂,因为必须确定一个账户的类型后才能使用相应的最小余额。确定一个特定对象是储蓄账户还是经常账户需要附加处理和数据值。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 6 页,共 9 页 - - - - - - - - - 如果用单个类作为两个或多个实体的模型不是好的设
17、计,那么我们是否应该为每个不同类型的实体设计单独的类? 对前面的例子,我们应该定义两个类:Savings Account和CheckingAccount 。这种选择也不是好的设计,因为最终还是要复制这些方法。例如,如果我们从储蓄账户扣除取款金额的方式与检查经常账户的方式相同,那么我们将不得不为这两个类定义完全相同的方法,复制相同的代码。数据值复制问题从而还可能随方法复制出现。因此两种选择都有问题,所以在面向对象的程序设计中,我们实际使用一种称为“继承”(inheritance)的机制设计两个或多个不同但有许多共同特征的实体。首先我们定义一个包括实体共同特征的类,然后定义公共类的扩展类,扩展类继
18、承公共类的所有成员。我们将公共类称为超类 (superclass),而由公共类继承的类称为子类(subclass).超类还称为祖先(ancetor),子类称为后代 (descendant)。对于银行的例子,我们可以定义一个Account超类,然后定义Savings 和 Checking 作为 Account 的子类。我们按图2.12 所示那样表示超类及其子类。注意,我们之所以画出从子类指向超类的箭头,是因为子类可以引用其超类中定义的项,但反之不行。图 2.12 超类 Account 及其子类 Savings和 Checking 子类将继承其超类的所有成员,我们不能说我们需要子类继承超类的50%
19、,然而子类重载继承的部分是可能的。例如,Account 类定义了一个100 美元 minimum balance 的类变量,而Saving 类用250 美元重载此值。继承的其他部分成份也可以被重载。举例来说,Checking 类可以通过增加适用于该类实例的指令重载继承的deduct 方法(例如,在任何一个指定的月份开出超过10 张支票以后, 每回收一张的费用是1 美元 )。子类还可以在由其超类继承的部分增加方法和数据成员,Checking 类可以增加一个新的实例变量保存一个月中开出支票的数量。继承不限于一层,子类可以是其他类的超类,从而形成继承的层次结构。思考图2.13所示的例子。 继承性是非
20、常强大的,如果使用正确, 我们即可非常有效精致地开发复杂的程序。使用强大工具的另一方面是如果不小心,则可能错误, 到最后也许陷入比不用它更糟的境地。贯穿全书,我们都将讨论继承和如何正确地使用它。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 7 页,共 9 页 - - - - - - - - - 2.13 不同类型帐号之间继承的层次结构的例子2.5 软件工程和软件生命周期当我们说到计算机程序设计(computer programming) 时,指的不仅是编写Java 语句,还包括整个
21、软件开发的过程。只懂得程序设计语言并不足以成为一个有造诣的软件开发人员,你必须知道如何设计程序。本书讲授如何以面向对象的方式设计程序。建房子时, 我们要分几个明确的阶段,每个阶段均遵循设计原则。类似地, 开发程序也要分为若干阶段,程序开发的每个阶段均遵循科学的方法。从程序的构思到运行所经过的各个阶段称为软件生命周期(Software Life Cycle),而软件工程(software engineering) 是运用系统、科学的方法开发、测试和维护程序。软件生命周期有5 个主要阶段:分析、设计、编写代码、测试和运行。软件的生命开始于顾客的需求,例如某人需要一个在线地址簿。分析 (analys
22、is)阶段完成可行性研究, 我们分析问题并确定解决方案是否可行。如果方案可行, 则此阶段的成果是描述程序功能的需求规范(requirements specification) 。程序功能必须以一种可以测试的方式陈述,地址簿程序的功能之一是通过指定他或她的名字查找某人。我们可以通过运行程序并实际查找某人测试这项功能。键入在地址簿中某人的名字和不在地址簿中某人的名字作为查找条件,检查程序运行是否符合要求。我们在测试阶段完成此测试,并简单说明。在设计 (design)阶段,需求规范变为程序的详细设计。对于面向对象的设计,此阶段的成果是一套满足需求的类对象。类对象必须完全定义,要说明其如何工作及之问如
23、何通信。对地址簿程序,我们可以设计Person、Phone和其他对象。在编写代码 (coding) 阶段,我们将设计实现为实际的程序,在本书中即实现C#程序。只要我们有一个周密的设计,然后将其实现为实际的代码其实不难,难的是设计。在本书中,我们将更多重点放在软件构造的设计方面。实现完成后,进入测试(testing)阶段。在这个阶段中, 我们用不同组数据运行程序,检验程序运行是否符合需求规范。对于面向对象的程序有两种类型的测试:单元测试(unit testing)和综合测试 (integration testing)。在单元测试过程中,我们一个一个单独地测试类。在综合测试过程中,我们测试所有类在
24、一起工作时是否正确。排除程序设计错误的行为称为“调试(debugging),错误可能是不完善的实现或有缺陷的设计造成的结果。如果存在错误,则必须退到前面的阶段以排除错误。最后测试成功之后,进入运行(operation)阶段,在这个阶段中程序将投入实际使用。运行阶段中,最重要而且最耗时的工作是软件维护(software maintenance) 。软件投入使用后,我们几乎始终都不得不对其做出修改。例如客户可能要求增加其他功能,或者可能发现以前未检测出的错误。软件维护意味着修改软件。据估计,近70的软件成本与软件维护有关。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - -
25、 - - - - - - - - - 名师精心整理 - - - - - - - 第 8 页,共 9 页 - - - - - - - - - 因此当开发软件时,我们应该很自然地以软件易于维护为目标。我们绝不能为了减少软件开发成本而仓促地开发,应该花时间小心谨慎地设计,然后正确地编写代码,哪怕一开始花费更长的时问和更多的丌销。从长远来看, 精心设计的软件终究将有更低的总成本,这是因为减少了维护成本。请记住一个重要的观点:精心设计和精心构造的软件易于维护。本书中, 我们的重点是设计、编写代码和测试阶段,我们将以问题陈述的形式介绍本书中开发的示例程序的需求规范。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 9 页,共 9 页 - - - - - - - - -