第2章 程序设计基础[视频讲解]
1程序设计方法与风格。
2结构化程序设计。
3面向对象的程序设计方法,对象,方法,属性及继承与多态性。
2.1 程序设计方法与风格
视频二维码(扫码观看)
程序设计是一门技术,需要相应的理论、技术、方法和工具来支持。程序设计方法和技术的发展主要经过了结构化程序设计和面向对象的程序设计阶段。
程序设计风格会深刻地影响软件的质量和可维护性,良好的程序设计风格可以使程序结构清晰合理,使程序代码便于维护,因此,程序设计风格对保证程序的质量是很重要的。
程序设计风格指编写程序时所表现出的特点、习惯和逻辑思路。著名的“清晰第一,效率第二”的论点已成为当今主导的程序设计风格。
要形成良好的程序设计风格,主要应注重和考虑下述因素:
1源程序文档化
(1)符号名的命名
符号名的命名应具有一定的实际含义,以便于对程序功能的理解。
(2)程序注释
正确的注释能够帮助读者理解程序。注释一般分为序言性注释和功能性注释。
①序言性注释
通常位于每个程序的开头部分,它给出程序的整体说明,主要描述内容可以包括:程序标题、程序功能说明、主要算法、接口说明、程序位置、开发简历、程序设计者、复审者、复审日期、修改日期等。
②功能性注释
功能性注释的位置一般嵌在源程序体之中,主要描述其后的语句或程序做什么。
(3)视觉组织
为使程序的结构一目了然,可以在程序中利用空格、空行、缩进等技巧使程序层次清晰。
2数据说明的方法
在编写程序时,需要注意数据说明的风格,以便使程序中的数据说明更易于理解和维护。一般应注意如下几点:
(1)数据说明的次序规范化。鉴于程序理解、阅读和维护的需要,使数据说明次序固定,可以使数据的属性容易查找,也有利于测试、排错和维护。
(2)说明语句中变量安排有序化。说明语句包含多个变量时,变量按照字母顺序排序为好。
(3)使用注释来说明复杂数据的结构。
3语句的结构
程序应该简单易懂,语句构造应该简单直接,不应该为提高效率而把语句复杂化。一般应注意如下:
①在一行内只写一条语句;
②程序编写应优先考虑清晰性;
③除非对效率有特殊要求,程序编写要做到“清晰第一,效率第二”;
④首先要保证程序正确,然后才要求提高速度;
⑤避免使用临时变量而使程序的可读性下降;
⑥避免不必要的转移;
⑦尽可能使用库函数;
⑧避免采用复杂的条件语句;
⑨尽量减少使用“否定”条件的条件语句;
⑩数据结构要有利于程序的简化;
⑪要模块化,使模块功能尽可能单一化;
⑫利用信息隐蔽确保每一个模块的独立性;
⑬从数据出发去构造程序;
⑭不要修补不好的程序,要重新编写。
4输入和输出
输入和输出信息是用户直接关系的,输入和输出方式和格式应尽可能方便用户的使用,因为系统能否被用户接受,往往取决于输入和输出的风格。无论是批处理的输入和输出方式,还是交互式的输入和输出方式,在设计和编程时都应该考虑如下原则:
①所有的输入数据都要检验数据的合法性;
②检查输入项的各种重要组合的合理性;
③输入格式要简单,以使得输入的步骤和操作尽可能简单;
④输入数据时,应允许使用自由格式;
⑤应允许缺省值;
⑥输入一批数据时最好使用输入结束标志;
⑦在以交互式输入/输出方式进行输入时,要在屏幕上使用提示符明确提示输入的请求,同时在数据输入过程中和输入结束时,应在屏幕上给出状态信息;
⑧当程序设计语言对输入格式有严格要求时,应保持输入格式与输入语句的一致性;给所有的输出加注释,并且设计输出报表格式。
2.2 结构化程序设计
视频二维码(扫码观看)
20世纪70年代提出了“结构化程序设计(Structured Programming)”的思想和方法。结构化程序设计方法引入了工程思想和结构化思想,使大型软件的开发和编程都得到了极大的改善。
一、结构化程序设计的原则
结构化程序设计方法的主要原则可以概括为自顶向下,逐步求精,模块化,限制使用goto语句。
1自顶向下
程序设计时,应先考虑总体,后考虑细节;先考虑全局目标,后考虑局部目标。不要一开始就过多追求众多的细节,先从最上层总目标开始设计,逐步使问题具体化。
2逐步求精
对复杂问题,应设计一些子目标作过渡,逐步细化。
3模块化
一个复杂问题,肯定是由若干稍简单的问题构成。模块化是把程序要解决的总目标分解为分目标,再进一步分解为具体的小目标,把每个小目标称为一个模块。
4限制使用goto语句
(1)肯定的结论
①在块和进程的非正常出口处往往需要用goto语句,使用goto语句会使程序执行效率较高;
②在合成程序目标时,goto语句往往是有用的,如返回语句用goto。
(2)否定的结论
①goto语句是有害的,是造成程序混乱的祸根,程序的质量与goto语句的数量成反比,应该在所有高级程序设计语言中取消goto语句;
②取消goto语句后,程序易理解、易排错、易维护,程序容易进行正确性证明。
(3)争论的结论
1974年Knuth发表了令人信服的总结,并证实了:
①滥用goto语句确实有害,应尽量避免;
②完全避免使用goto语句也并非是个明智的方法,有些地方使用goto语句,会使程序流程更清楚、效率更高;
③争论的焦点不应该放在是否取消goto语句,而应该放在用在什么样的程序结构上。
其中最关键的是肯定以提高程序清晰性为目标的结构化方法。
二、结构化程序的基本结构与特点
1结构化程序的基本结构
结构化程序设计方法是程序设计的先进方法和工具。采用结构化程序设计方法编写程序,可使程序结构良好、易读、易理解、易维护。
1966年,Boehm和Jaeopini证明了程序设计语言仅仅使用顺序、选择和循环三种基本控制结构就足以表达出各种其他形式结构的程序设计方法。
(1)顺序结构
顺序结构是一种简单的程序设计,它是最基本、最常用的结构,
顺序结构是顺序执行结构,所谓顺序执行,就是按照程序语句行的自然顺序,一条语句一条语句地执行程序。
图2-1 顺序结构
(2)选择结构
选择结构又称为分支结构,它包括简单选择和多分支选择结构,这种结构可以根据设定的条件,判断应该选择哪一条分支来执行相应的语句序列。
图2-2 选择结构
(3)循环结构
循环结构根据给定的条件,判断是否需要重复执行某一相同的或类似的程序段,利用循环结构可简化大量的程序行。在程序设计语言中,循环结构对应两类循环语句,对先判断后执行循环体的称为当型循环结构;对先执行循环体后判断的称为直到型循环结构。
图2-3 当型循环结构
图2-4 直到型循环结构
2结构化程序的特点
遵循结构化程序的设计原则,按结构化程序设计方法设计出的程序具有明显的优点:
(1)程序易于理解、使用和维护
程序员采用结构化编程方法,便于控制、降低程序的复杂性,因此容易编写程序。便于验证程序的正确性,结构化程序清晰易读,可理解性好,程序员能够进行逐步求精、程序证明和测试,以确保程序的正确性,程序容易阅读并被人理解,便于用户使用和维护。
(2)提高了编程工作的效率,降低了软件开发成本
由于结构化编程方法能够把错误控制到最低限度,因此能够减少调试和查错时间。结构化程序是由一些为数不多的基本结构模块组成,这些模块甚至可以由机器自动生成,从而极大地减轻了编程工作量。
三、结构化程序设计原则和方法的应用
基于对结构化程序设计原则、方法以及结构化程序基本构成结构的掌握和了解,在结构化程序设计的具体实施中,要注意把握如下要素:
①使用程序设计语言中的顺序、选择、循环等有限的控制结构表示程序的控制逻辑。
②选用的控制结构只准许有一个入口和一个出口。
③程序语句组成容易识别的块,每块只有一个入口和一个出口。
④复杂结构应该用嵌套的基本控制结构进行组合嵌套来实现。
⑤语言中所没有的控制结构,应该采用前后一致的方法来模拟。
⑥严格控制goto语句的使用。即:
a.用一个非结构化的程序设计语言去实现一个结构化的构造;
b.若不使用goto语句会使功能模糊;
c.在某种可以改善而不是损害程序可读性的情况下。
【考题1】结构化程序设计主要强调的是( )。
A.程序的规模
B.程序的易读性
C.程序的执行效率
D.程序的可移植性
【答案】B
【解析】根据“清晰第一,效率第二”的原则,选项B正确。
【考题2】对建立良好的程序设计风格,下面描述正确的是( )。
A.程序应简单、清晰、可读性好
B.符号名的命名只要符合语法
C.充分考虑程序的执行效率
D.程序的注释可有可无
【答案】A
【解析】根据“清晰第一,效率第二”的原则,选项A正确,选项C错误;符号名的命名应具有一定的实际含义,以便于对程序功能的理解,选项B错误;正确的注释能够帮助读者理解程序,选项D错误。
2.3 面向对象的程序设计
视频二维码(扫码观看)
一、关于面向对象方法
自20世纪80年代中期开始,面向对象(Object Oriented)方法已经发展成为主流的软件开发方法。
1面向对象方法的发展
(1)面向对象的软件开发方法在20世纪60年代后期首次提出,以60年代末挪威奥斯陆大学和挪威计算中心共同研制的SIMULA语言为标志,面向对象方法的基本要点首次在SIMULA语言中得到了表达和实现。
(2)后来一些著名的面向对象语言(如Smalltalk、C++、Java)的设计者都曾从SIMULA得到启发。随着20世纪80年代美国加州的Xerox研究中心推出Smalltalk语言和环境,使面向对象程序设计方法得到比较完善的实现。
(3)Smalltalk-80等一系列描述能力较强、执行效率较高的面向对象编程语言的出现,标志着面向对象的方法与技术开始走向实用。
2面向对象方法的本质
主张从客观世界固有的事物出发来构造系统,提倡用人类在现实生活中常用的思维方法来认识、理解和描述客观事物,强调最终建立的系统能够映射问题域,也就是说,系统中的对象以及对象之间的关系能够如实地反映问题域中固有事物及其关系。
3面向对象方法的优点
(1)与人类习惯的思维方法一致
面向过程的程序设计核心思想是以算法为核心,把数据和过程作为相互独立的部分,数据代表问题空间中的客体,程序则用于处理这些数据数据和程序是分开存放的。
存在的问题:
会出现使用错误的数据调用正确的程序模块;忽略了数据和操作之间的内在联系;会出现解空间与问题空间不一致;
解决办法:
具体事物都具有行为和属性两方面的特征。因此,把描述事物静态属性的数据结构和表示事物动态行为的操作放在一起构成一个整体,才能完整自然地表示客观世界中的实体。
面向对象的方法:
以对象为核心。对象是由数据和容许的操作组成的封装体,与客观实体有直接的对应关系。对象之间通过传递消息互相联系,以模拟现实世界中不同事物彼此之间的联系。
基本原理:使用现实世界的概念抽象地思考问题从而自然地解决问题。它强调模拟现实世界中的概念而不强调算法,它鼓励开发者在软件开发的绝大部分过程中都用应用领域的概念去思考。
(2)稳定性好
面向对象方法基于构造问题领域的对象模型,以对象为中心构造软件系统。
传统的软件开发方法:
传统的软件开发方法以算法为核心,开发过程基于功能分析和功能分解。用传统方法所建立起来的软件系统的结构紧密地依赖于系统所要完成的功能,当功能需求发生变化时将引起软件结构的整体修改。事实上,用户需求变化大部分是针对功能的;因此,这样的软件系统是不稳定的。
面向对象的方法:
基本做法:用对象模拟问题领域中的实体,以对象间的联系刻画实体间的联系。因为面向对象的软件系统的结构是根据问题领域的模型建立起来的,而不是基于对系统应完成的功能的分解,所以,当对系统的功能需求变化时并不会引起软件结构的整体变化,往往仅需要做一些局部性的修改。
由于现实世界中的实体是相对稳定的,因此,以对象为中心构造的软件系统也是比较稳定的。
(3)可重用性好
软件重用:是指在不同的软件开发过程中重复使用相同或相似软件元素的过程。重用是提高软件生产率的最主要的方法。
传统的软件重用技术:
传统的软件重用技术是利用标准函数库。标准函数缺乏“柔性”,不能适应不同应用场合的不同需要,不是理想的可重用的软件成分。
面向对象的方法:
在面向对象方法中所使用的对象,其数据和操作是作为平等伙伴出现的。因此,对象具有很强的自含性,此外,对象所固有的封装性,使得对象的内部实现与外界隔离,具有较强的独立性。由此可见,对象提供了比较理想的模块化机制和比较理想的可重用的软件成分。
重复使用一个对象类的方法:
①创建该类的实例,从而直接使用它;
②从它派生出一个满足当前需要的新类。
继承性机制使得子类不仅可以重用其父类的数据结构和程序代码,而且可以在父类代码的基础上方便地修改和扩充,这种修改并不影响对原有类的使用。
(4)易于开发大型软件产品
当开发大型软件产品时,组织开发人员的方法不恰当往往是出现问题的主要原因。用面向对象范型开发软件时,可以把一个大型产品看作是一系列本质上相互独立的小产品来处理,这就不仅降低了开发的技术难度,而且也使得对开发工作的管理变得容易。许多软件开发公司的经验都表明,当把面向对象技术用于大型软件开发时,软件成本明显地降低了,软件的整体质量也提高了。
(5)可维护性好
①开发软件稳定性比较好。当软件功能或性能要求发生变化时,不会引起软件的整体变化,只需对局部做一些修改。
②开发软件比较容易修改。如果仅修改一个类的内部实现部分,而不修改该类的对外接口,则可以完全不影响软件的其他部分。
面向对象技术的继承机制,软件的修改和扩充通常只需从已有类派生出一些新类,无需修改软件原有成分。
面向对象技术的多态性机制,使得当扩充软件功能时对原有代码的修改进一步减少,需要增加的新代码也比较少。
③开发的件比较容易理解
面向对象的技术符合人们习惯的思维方式,用这种方法所建立的软件系统的结构与问题空间的结构基本一致。因此,面向对象的软件系统比较容易理解。
④易于测试和调试
对用面向对象的方法开发的软件进行维护,往往是通过从已有类派生出一些新类来实现。因此,维护后的测试和调试工作也主要围绕这些新派生出来的类进行。
二、面向对象方法的基本概念
1对象(Object)
对象是面向对象方法中最基本的概念。对象可以用来表示客观世界中的任何实体,它既可以是具体的物理实体的抽象,也可以是人为的概念,或者是任何有明确边界和意义的东西。如,一个人、一家公司、一个窗口等,都可以作为一个对象。
面向对象的程序设计方法中涉及的对象是系统中用来描述客观事物的一个实体,是构成系统的一个基本单位,它由一组表示其静态特征的属性和它可执行的一组操作组成。
属性即对象所包含的信息,它在设计对象时确定,一般只能通过执行对象的操作来改变。属性值应该指的是纯粹的数据值,而不能指对象。
操作描述了对象执行的功能,若通过消息传递,还可以为其他对象使用。通常把对象的操作也称为方法或服务。
事实上,操作过程已经封装在对象中,用户也看不到。对象的这一特性,即是对象的封装性。
【例1】一辆汽车是一个对象,它包含了汽车的属性(如颜色、型号、载重量等)及其操作(如启动、刹车等)。一个窗口是一个对象,它包含了窗口的属性(如大小、颜色、位置等)及其操作(如打开、关闭等)。
对象的基本特点:
①标识唯一性。指对象是可区分的,并且由对象的内在本质而不是描述来区分。
②分类性。指可以将具有相同属性和操作的对象抽象成类。
③多态性。指同一个操作可以是不同对象的行为。
④封装性。从外面看只能看到对象的外部特性,即只需知道数据的取值范围和可以对该数据施加的操作,无需知道数据的具体结构以及实现操作的算法。对象的内部,即处理能力的实行和内部状态,对外是不可见的。从外面不能直接使用对象的处理能力,也不能直接修改其内部状态,对象的内部状态只能由其自身改变。
⑤模块独立性好。对象是面向对象的软件的基本模块,它是由数据及可以对这些数据施加的操作所组成的统一体,而且对象是以数据为中心的,操作围绕对其数据所需做的处理来设置,没有无关的操作。从模块的独立性考虑,对象内部各种元素彼此结合得很紧密,内聚性强。
【考题】信息隐蔽的概念与下述哪一种概念直接相关( )。
A.软件结构定义
B.模块独立性
C.模块类型划分
D.模块耦合度
【答案】B
【解析】信息隐蔽指的是模块的独立性。
2类(Class)和实例(Instance)
类是具有共同属性、共同方法的对象的集合。类是对象的抽象,它描述了属于该对象类型的所有对象的性质,而一个对象则是其对应类的一个实例。
【注意】当使用“对象”这个术语时,既可以指一个具体的对象,也可以泛指一般的对象,但是,当使用“实例”这个术语时,必然是指一个具体的对象。
【例2】Integer是一个整数类,它描述了所有整数的性质。因此任何整数都是整数类的对象,而一个具体的整数“123”是类Integer的一个实例。
【例3】一个面向对象的图形程序在屏幕左下角显示一个半径3cm的红颜色的圆,在屏幕中部显示一个半径4cm的绿颜色的圆,在屏幕右上角显示一个半径1cm的黄颜色的圆。这三个圆心位置、半径大小和颜色均不相同的圆,是三个不同的对象。但是,它们都有相同的属性(圆心坐标、半径、颜色)和相同的操作(显示自己、放大缩小半径、在屏幕上移动位置,等等)。因此,它们是同一类事物,可以用“Circle类”来定义。
【考题】将十进制整数设为整数类Ⅰ,则下面属于类Ⅰ的实例的是( )。
A.0x1f
B.0.51
C.-51
D.518E-2
【答案】C
【解析】选项A,0x1f是十六进制数;选项B,0.51是小数;选项C符合题意;选项D,518E-2不是整数。
3消息(Message)
面向对象的世界是通过对象与对象间彼此的相互合作来推动的,对象间的这种相互合作需要一个机制协助进行,这样的机制称为“消息”。
消息是一个实例与另一个实例之间传递的信息,它请求对象执行某一处理或回答某一要求的信息,它统一了数据流和控制流。消息的使用类似于函数调用,消息中指定了某一个实例,一个操作名和一个参数表(可空)。
图2-5 消息传递示意图
通常,一个消息由下述三部分组成:
①接收消息的对象的名称;
②消息标识符(也称为消息名);
③零个或多个参数。
【例4】一个汽车对象具有“行驶”这项操作,那么要让汽车以时速50公里行驶的话,需传递给汽车对象“行驶”及“时速50公里”的消息。
【考题】在面向对象方法中,一个对象请求另一对象为其服务的方式是通过发送( )。
A.调用语句
B.命令
C.口令
D.消息
【答案】D
【解析】两个对象之间,请求服务的时候,通过传递消息互相联系。
4继承(Inheritance)
(1)定义
继承是使用已有的类定义作为基础建立新类的定义技术。已有的类可当做基类来引用,则新类相应地可当做派生类来引用。
广义地说,继承是指能够直接获得已有的性质和特征,而不必重复定义它们。
一个类的上层可以有父类,下层可以有子类。这种层次结构系统的一个重要性质是继承性,一个类直接继承其父类的描述(数据和操作)或特性,子类自动地共享基类中定义的数据和方法。
图2-6 实现继承机制的原理图
继承具有传递性,如果类C继承类B,类B继承类A,则类C继承类A。一个类实际上继承了它上层的全部基类的特性。
(2)分类
继承分为单继承与多重继承。
单继承,是指一个类只允许有一个父类,即类等级为树形结构。
多重继承,是指一个类允许有多个父类。使用多重继承时要注意避免二义性。
(3)继承的优点
相似的对象可以共享程序代码和数据结构,从而大大减少了程序中的冗余信息,提高软件的可重用性,便于软件修改维护。
另外,继承性使得用户在开发新的应用系统时不必完全从零开始,可以继承原有的相似系统的功能或者从类库中选取需要的类,再派生出新的类以实现所需要的功能。
【考题】下面对对象概念描述错误的是( )。
A.任何对象都必须有继承性
B.对象是属性和方法的封装体
C.对象间的通信靠消息传递
D.操作是对象的动态属性
【答案】A
【解析】类有继承机制,对象没有。
5多态性(Polymorphism)
(1)定义
对象根据所接收的消息而做出动作,同样的消息被不同的对象接收时可导致完全不同的行动,该现象称为多态性。
在面向对象的软件技术中,多态性是指子类对象可以像父类对象那样使用,同样的消息既可以发送给父类对象也可以发送给子类对象。
【例5】在两个类Male(男性)和Female(女性)都有一项属性为Friend。一个人的朋友必须属于类Male或Female,这是一个多态性的情况。因为,Friend指向两个类之一的实例。如果Tom的朋友或者是Mary或者是John,类Male就不知道Friend应该与哪个类关联。这里参照量Friend必须是多态的,多态意味着可以关联不同的实例,而实例可以属于不同的类。
(2)多态性的优点
多态性机制不仅增加了面向对象软件系统的灵活性,进一步减少了信息冗余,而且显著地提高了软件的可重用性和可扩充性。
当扩充系统功能增加新的实体类型时,只需派生出与新实体类相应的新的子类,完全无需修改原有的程序代码,甚至不需要重新编译原有的程序。
利用多态性,用户能够发送一般形式的消息,而将所有的实现细节都留给接收消息的对象。