面向对象程序设计概述.docx
《面向对象程序设计概述.docx》由会员分享,可在线阅读,更多相关《面向对象程序设计概述.docx(19页珍藏版)》请在冰点文库上搜索。
面向对象程序设计概述
第1章面向对象程序设计概述
近年来,面向对象程序设计思想已经被越来越多软件设计人员所接受。
它是在吸取构造化程序设计一切长处基本上发展起来一种新程序设计思想。
这种新思想更接近人思维活动,人们运用这种思想进行程序设计时,可以很大限度地提高编程能力,减少软件维护开销。
面向对象系统最突出特点是封装性、继承性和多态性。
1.1什么是面向对象程序设计
在软件设计和实现中,老式被人们广泛用法是面向过程程序设计办法。
在讨论面向对象程序设计之前,咱们需要讨论一下面向过程程序设计。
1.1.1面向过程程序设计基本概念
面向过程程序设计思想核心是功能分解:
第一步要做工作就是将问题分解成若干个称为模块功能块;
第二步依照模块功能来设计一系列用于存储数据数据构造;
第三步编写某些过程(或函数)对这些数据进行操作。
显然,这种办法将数据构造和过程作为两个实体来对待,其着重点在过程。
设计人员一方面考虑如何将功能分解,在每一种过程中又要着重安排程序操作序列,但同步程序员在编程时又必要时时考虑数据构造,由于毕竟要将操作作用于数据上。
数据构造和过程这种分离,给软件人员导致沉重承担。
例如,咱们不也许规定数据构造始终没有变化,且不说在软件维护时候数据构造有也许发生变化,就是在软件开发过程中也不能保证数据构造不变化。
面向过程程序设计缺陷之一就是一旦数据构造需要变更时候,必要修改与之关于所有模块。
因而,面向过程程序可重用性差,维护代价高。
下面,咱们举一种实例来进一步讨论面向过程程序设计办法。
考虑一种银行系统。
该系统容许顾客开设不同类型银行账户,其中涉及钞票账户、支票账户和贷款账户,同步容许顾客存款、取款和转账。
依照面向过程程序设计办法,一方面咱们将银行系统分解成三个模块分别负责存款、取款和转账三项工作。
这三个过程是MakeDeposit、WithDraw和Transfer。
接着,建立一种简朴数据构造:
structaccount{
charname;/*姓名*/
unsignedlongaccountld;/*账号*/
floatbalance/*余额*/
floatinterestYTD/*年利息*/
characcountType./*账户类型(钞票、支票和贷款)*/
};
然后,对每个过程按照一定操作顺序编写程序。
咱们来分析一下,程序员所关怀与否与顾客一致。
(1)对于一种顾客来说,她最关怀是账户中尚有多少钱,利息是多少,钱存在银行与否安全,而不会对存钱和取钱程序执行过程感兴趣。
对她而言,只是需要懂得存、取款手续,并按照这些手续去做就足够了。
(2)程序设计人员所关注是如何写存、取款代码,如何在已经建立数据构造中填写数据并管理它们。
可见,程序员与顾客关怀事情是不一致,这是由于数据构造与“过程”分离导致。
再进一步分析,顾客与她们银行账户有无特殊关系。
在软件系统中,由于顾客只但是是一串字符和数字,因而不用考虑究竟是谁拥有该账户,账户里内容是什么,而银行账号也只但是是一种整数。
此外,由于数据构造与“过程”分离,程序员可以非常以便地修改账目,由于对她来说,只但是是在修改数据构造中数字,事实上她也许通过修改数据而取走顾客钱。
最后,咱们考虑如果数据构造发生了某些变化会产生什么样成果。
对于accountType数据项,本来只有钞票账户、支票账户和贷款账户三种取值,程序只能辨认这三种取值。
由于账户类型不同,咱们在编写存款等过程时,将以不同操作序列与之相应(在同一种过程中分状况解决)。
对钞票账户、支票账户和贷款账户解决不会完全相似。
假设当前需要增长一种账户类型——退休账户,后果如何?
本来程序必定出错。
由于在本来程序中咱们只考虑了以上三种账户状况,对于新增长账户类型,本来程序不会解决。
也就是说,每增长一种新账户类型,都必要重新编写程序代码,可见其维护软件开销是相称大。
上述这些问题浮现都是由于面向过程程序设计解决办法着重点在功能,而咱们通过度析发现,数据对于客户(特别是顾客)似乎更重要。
在这里,程序员关怀是如何做(howtodo),而顾客则关怀是做什么(whatt0do),这是由于过程和数据分离导致。
使用面向对象程序设计技术是解决这些问题最佳办法。
1.1.2面向对象程序设计基本概念
在面向对象程序设计中,着重点在那些将要被操作数据,而不是在实现这些操作过程。
数据构成了软件分解基本,而不是功能。
咱们一方面要分析顾客在账户(数据)中要做什么,然后提供相应操作,更重要是不能将数据和相应操作当作两个分离实体,而是要把它们作为一种完整实体来对待。
数据与定义在它上面顾客需要操作构成一种整体。
同步,数据自身不能被外部程序和过程直接存取。
如果想修改银行账户中数据,惟一办法是在该数据上提供修改操作,这些修改操作是以顾客应得到利益为依照。
当咱们把对银行账户操作定义在数据上,银行账户就是一种类,称为银行账户类。
作为其实例,咱们可以建立许多详细银行账户,而每一种详细银行账户就是银行账户类一种对象。
当前,咱们给面向对象程序设计下一种定义。
面向对象程序设计是一种新程序设计范型。
面向对象程序重要构造特点是:
第一,程序普通由类定义和类使用两某些构成,在主程序中定义各对象并规定它们之间传递息规律;
第二,程序中一切操作都是通过向对象发送消息来实现,对象接受到消息后,启动关于办法完毕相应操作。
面向对象程序设计最大长处就是软件具备可重用性。
当人们对软件系统规定有所变化时,并不需要程序员做大量工作,就能使系统做相应变化。
类与对象是面向对象程序设计中最重要概念,也是一种难点,想要掌握面向对象程序设计技术,一方面就要较好地理解这两个概念。
1.2对象与类
1.2.1对象与类概念
在现实世界中,人们是如何结识“对象”和“类”。
在寻常生活中对象就是咱们结识世界基本单元,它可以是人,也可以是物,还可以是一件事。
整个世界就是由形形色色“对象”构成。
例如一辆车、一种球、一种小学生、一次表演。
对象既可以很简朴,也可以很复杂,复杂对象可以由若干简朴对象构成。
对象是现实世界中一种实体,其特性是:
(1)每一种对象必要有一种名字以区别于其他对象;
(2)用属性(或叫状态)来描述它某些特性;
(3)有一组操作,每一种操作决定对象一种行为。
在寻常生活中,“类”是对一组具备共同属性特性和行为特性对象抽象。
例如,由一种个人构成人类,而一种人是人类一种实例。
类和对象之间关系是抽象和详细关系。
类是对各种对象进行综合抽象成果,对象又是类个体实物,一种对象是类一种实例。
例如,教师黎明和学生李明都是一种对象。
对象名:
黎明对象名:
李明
对象属性:
对象属性:
年龄:
30年龄:
20
学历:
博士学历:
本科
职称:
专家性别:
男
专业:
计算机软件专业:
计算机科学与技术
对象操作:
对象操作:
说自己年龄打篮球
吃饭睡觉
授课听课
一种个像黎明这样教师就构成教师类。
一种个像李明这样学生就构成学生类。
咱们前面说过,面向对象程序设计更接近人们思维。
面向对象程序设计中对象和就来源于现实世界。
以面向对象程序设计观点看,一种对象是由描述其属性数据和定义在其上面一组操作构成实体,是数据单元和过程单元组合体。
类是对一组对象抽象,这组对象具备相似属性构造和操作行为,在对象所属类中要阐明这些构造和行为。
一种对象是类一种实例。
有了类,才可以创立对象。
当前咱们给出类更精准定义:
类是创立对象样板,它包括对创立对象状态描述和对操作行为阐明。
如果用面向对象观点来分析银行账户问题,着重点在银行账户上,而不是在存款和取款行为上,那么,银行账户就是一种类。
classBankAccount{
public:
voidMakeDeposit(floatamount);
floatWithDraw(floatamount);
boolTransfer(BankAccount&to,floatamount);
private:
floatbalance;
floatinterestYTD;
char*owner;
intaccount_number;
);
在BankAccount类中,阐明行为是MakeDeposit、WithDraw和Transfer。
这些行为对于任何客户来说是很重要,她们在银行开户目就是要进行存款、取款以及转账。
正由于每一种顾客(作为类实例)都也许做这些操作,因此对行为阐明是public,即公有。
同步,在BankAecount类中,还阐明了数据balance、interestYTD、owner和account—number,这些数据是私有,只能在被定义类中进行操作。
作为银行账户类实例,银行每一种银行账户都是一种对象。
每个银行账户对象有相似构造和行为。
因而,任何一种银行账户对象都可以使用在类中阐明MakeDeposit等操作,并且每个银行账户对象有相似类型数据构造balance等。
在面向对象程序设计中,一种类只在源程序代码中浮现,而并不会在一种正在内存运营程序中浮现,即类只是在编译时存在;对象作为类实例在运营程序中浮现,并占有内存空间,它是在运营时存在实体。
因此一种类事实上是一种新数据类型,当咱们要用一种新数据类型时,一方面要在源程序中阐明,而阐明某些代码是不在内存中运营。
在程序中运营是该类对象,对象在内存完毕。
注意,咱们在此必要严格区别阐明和定义。
前面咱们用C++写程序段是对类BankAccount阐明。
在c++类中,咱们把那些行为称为成员函数,而把数据称为数据成员。
1.2.2对象状态
在面向对象程序设计中,对象是类实例。
对象给类以生命,类想要做事必要通过建立对象和在对象上进行操作而实现。
创立类对象过程也叫实例化对象。
对象懂得什么能做和什么不能做,并且有能力修改和维护定义在对象上数据。
可以将对象当作是一种带有状态和行为活实体。
属于同一种类中对象具备相似行为,但是有各自独立状态。
什么是对象状态?
在现实世界中一种对象能独立存在因素是它们有各自特性,这些特性就是对象状态。
对于一种人来说,姓名、性别、身高都是其状态。
在前面讨论中,对象属性与对象状态是相似概念。
这里,给对象状态下一种定义:
对象状态是所有静态属性和这些属性动态值总和。
,
以银行账户为例,BankAccount类对象有一项数据成员balance(余额)。
假设银行不容许透支,那么每个账户余额(balance)不应不大于零。
这是所有银行账户类对象公共属性,也可以说是任何一种银行账户类对象静态属性。
此类属性是不需要检测。
然而,在BankAccount类对象生存期任何时刻,账户中余额是包括在balance这个数据成员中数值。
当在对象上发生存款、转账、取款等行为时,会引起该数值变化。
因而,账户余额是一种动态变化值,换句话说,数据成员balance值是动态。
对象状态普通不但仅是初等数据类型(整型、实型、字符型等),并且许多对象将另一种对象作为它们状态一某些。
例如,一辆车有发动机、车轮、座位,发动机是此外一种对象,它可以作为车状态一某些,。
又例如,一种银行对象可以将银行账户对象和顾客对象作为它状态一某些。
一辆车一种学校
1.2.3对象交互
现实世界中对象不是孤立存在实体,她们之间存在着各种各样联系,正是它们之间互相作用、联系和连接,才构成了世间各种不同系统。
同样,在面向对象程序设计中,对象之间也需要联系,咱们称为对象交互。
面向对象程序设计技术必要提供一种机制,容许一种对象与另一种对象交互。
这种机制叫消息传递。
在面向对象程序设计中消息传递,实际是对现实世界中信息传递直接模仿。
一种对象向另一种对象发出祈求被称为“消息”。
消息是一种对象规定另一种对象执行某个功能操作规格阐明,通过消息传递才干完毕对象之间互相祈求或互相协作。
例如,咱们有一种银行账户对象和一种顾客对象,顾客对象可以祈求银行账户对象服务,如“存入300元”、“取出200元”等,当银行账户对象接到祈求后,拟定应执行相应操作并执行。
在此,咱们有必要简介一下办法概念。
办法是面向对象程序设计中一种术语。
咱们懂得,属于一种类对象具备相似行为,当某个行为作用在对象时,咱们就称对象执行了一种办法。
办法定义了一系列计算环节。
因此,咱们可以说一种对象祈求另一种对象执行一种特定办法,或者说一种对象发送一种消息给另一种对象,引起那个对象办法执行。
从这个意义上看,对象行为是负责响应消息并进行操作。
普通状况下,咱们称发送消息对象为发送者或祈求者,接受消息对象为接受者或目的对象。
对象中联系只能通过消息传递来进行。
接受者只有在接受到消息时,才干被激活,被激活对象会依照消息规定完毕相应功能。
消息具备三个性质:
(1)同一种对象可以接受不同形式各种消息,做出不同响应;
(2)相似形式消息可以传递给不同对象,所做出响应可以是不同;
(3)消息发送可以不考虑详细接受者,对象可以响应消息,也可以不响应。
事实上,对象之间消息传递机制相应于面向过程程序设计过程调用。
消息传递并非真传递信息,它实质就是办法调用。
只但是办法调用受到消息控制,而过程调用是直接。
消息内容普通应涉及接受者名字、祈求办法、一种或各种参数。
由发送者向接受者发送一条消息,就是规定调用特定办法。
所调用办法也许引起对象状态变化,还也许会生成更多消息,而导致调用其他对象中办法。
在面向对象程序设计中,消息分为两类:
公有消息和私有消息。
假设有一批消息同属于一种对象,其中一某些消息是由其他对象直接向它发送,称为公有消息;另一某些消息是它向自己发送,称为私有消息。
公有消息与私有消息拟定,与消息规定调用办法关于。
如果被调用办法在对象所属类中是在public下阐明,则为公有;是在private下阐明,即为私有。
固然,私有消息只能发送调用属于它自己办法。
例如,一种银行账户对象类定义是BankAccount,一种顾客对象可以发送一种公有消息WithDraw给银行账户对象,规定取款。
这个消息是公有消息。
1.2.4类拟定与划分
咱们懂得,面向对象程序设计技术是将系统分解成若干对象,对象之间互相作用构成了整个系统。
而类是创立对象样板,在整体上代表一组对象,设计类而不是设计对象可以避免重复编码工作,类只需编码一次,就可以创立所有对象。
因此,当咱们辑决实际问题时,需要对的地进行分“类”。
咱们必要理解一种类究竟表达是哪一组对象,如何把实际问题中事物汇聚成一种个“类”,而不是一组数据。
这是面向对象程序设计中一种难点。
例如,考虑银行系统,咱们至少应当有两类对象:
顾客类和银行账户类。
学校系统应至少包括两类对象:
学生和教师。
如何拟定和划分类?
类拟定和划分并没有统一原则和固定办法,基本上依赖设计人员经验、技巧以及对实际问题把握。
一种基本原则是:
谋求一种大系统中事物共性,将具备共性系统成分拟定为一种类。
这里以模仿一种学校系统为例。
系统想要达到目的不同,拟定和划分类就不相似。
若模仿目是为了管理教学,设立类也许是学生、教师、教材、课程、教室、图书等。
若模仿目是管理后勤工作,设立类也许是宿舍、食堂、后勤工作人员、教室、图书馆等。
拟定一种事物是一种类第一步,是要判断它与否有一种以上实例,如果有,则它也许是一种类;第二步,咱们还要判断类实例中有否绝对不同点,如果没有,则它是一种类。
由于类每一种实例是相似,具备相似行为和属性构造。
例如,颜色(Color)与鲜花联系在一起只是鲜花一种状态,由于表达颜色是某些值:
红、黄、紫、白等,因此,在此Color不是一种类。
然而,如果咱们把颜色同涉及复杂颜色计算图形解决系统联系在一起,则Color是一种类,由于这时颜色是基于颜色三元素(红、绿、蓝)成分比例和色度变量,它不但仅是一种数值,还可以附带诸多行为。
不能把一组函数组合在一起构成类。
也就是说,不能把一种面向过程模块直接变成类。
如果简朴地将模块中函数变成成员函数而使其成为类是错误。
类不是函数集合。
例如,考虑一种包括一组数学函数模块,当前咱们定义一种类Mathhelper:
classMathelper{
public:
doublesqrt(doubleaNumber),
doublePower(doubleaNumber,intraiseto)‘
doubleInverse(doubleaNumber);
private:
//任何数据项,也也许没有
};
拟定Mathelper为一种类是错误。
问题在于该类中没有需要管理私有数据。
顾客只需要提供参数对成员函数进行调用。
这与面向过程程序设计函数调用没有主线区别。
设计类要有一种明确目的。
一种好类应当是容易理解和使用。
咱们不能设计一种Color类来表达鲜花颜色,但是可以在图形解决系统中将颜色Color设计为类。
由于在两个系统中对颜色规定不同。
1.3数据抽象与封装
面向对象系统中最突出特性是封装性、继承性和多态性。
咱们一方面来讨论封装性,封装与数据抽象概念密切有关。
1.3.1现实世界中抽象与封装
抽象和封装概念在现实世界中广泛存在,特别在科学技术日益发展今天,大量电器被人们使用,对电器使用体现了抽象与封装概念。
以录音机为例,录音机上有若干按键,当人们使用录音机时,只要依照自己需要,如放音、录音、停止、倒带等,按下与之相应键,录音机就会完毕相应工作。
这些按键安装在录音机表面,人们通过它们与录音机交互。
咱们无法(固然也没必要)操作录音机内部电路,由于它们被装在机壳里,录音机内部状况对于顾客来说是隐蔽,不可见。
这就是所谓封装原理。
那么,咱们是如何懂得放音按哪个键,停止又按哪个键呢?
是录音机操作阐明书告诉咱们,但操作阐明书并不告诉咱们录音机内部将如何去做这些事。
操作阐明书在录音机做什么(whattddo)与如何做(howtodo)之间做出了明确区别。
这就是所谓抽象原理。
抽象出来是做什么,而不关怀如何实现这些操作。
以普通观点而言,抽象是通过特定实例或例子抽取共同性质后来形成概念过程。
抽象是对系统简化描述或规范阐明,它强调了系统中一某些细节和特性,例如做什么,而忽视了其他某些,例如如何做。
抽象描述被称为它规范阐明,例如录音机操作阐明书,而对抽象解释称为它实现。
1.3.2数据抽象与封装基本概念
将上述观点用在数据构造上,就不难理解数据抽象与封装。
将数据构造和作用于数据构造上操作构成一种实体,数据表达方式和对数据操作细节被隐藏起来,顾客通过操作接口对数据进行操作。
对于顾客来说,只懂得如何通过操作接口对该数据进行操作,而并不懂得是如何做也不懂得数据是如何表达。
这就是数据封装。
数据抽象则是通过对数据实例分析,抽取其共同性质成果。
数据抽象和咱们前面讨论类概念之间显然存在着很强相似性。
在面向对象程序设计中,数据抽象是在拟定类时强调对象共同点而忽视它们不同点成果。
也可以说,在一种类阐明中咱们只表达那些重要特性,而忽视次要、引不起咱们兴趣东西。
数据封装则是隐藏了抽象内部实现细节成果。
封装是将数据抽象外部接口与内部实现细节清晰地分离开。
抽象和封装是互补。
好抽象有助于封装,封装实体则协助维护抽象完整性。
重要是抽象先于封装。
以银行账户类为例,balance、interestYTD、owner、account—number等私有数据是被封装数据,MakeDeposit、WithDraw、Transfer等成员函数细节也同步被封装,顾客看到是MakeDeposit、WithDraw、Transfer操作提供接口。
接口实现细节(不可见)
在上面讨论中,咱们并没有严格区别银行账户是类还是对象,由于封装性不但涉及到类描述,也涉及到构成软件系统对象。
从类实例——对象——角度来讨论封装似乎更合理,由于类并不真正占有存储空间。
封装单位实际是对象,但是对象构造和行为是用它自己类阐明来描述。
对象封装比类封装更详细化。
可以从下面几点来理解对象封装:
(1)对象具备一种清晰边界,对象私有数据、成员函数细节被封装在该边界内;
(2)具备一种描述对象与其他对象如何互相作用接口,该接口必要阐明消息传递用法;,
(3)对象内部代码和数据应受到保护,其他对象不能直接修改。
从顾客(或应用程序员)观点看,对象提供了一组服务,并提供了祈求服务接口。
从系统设计员角度看,封装能清晰地标明对象提供服务界面,而水乡行为和数据是隐蔽,不可见。
对象这一封装机制,可以将对象使用者和设计者分开。
1.3.3对象特性
(1)封装性。
(2)模块独立性。
(3)动态连接性。
(4)易维护性
1.4继承性
1.4.1继承概念
上图阐明了哺乳动物、狗、柯利狗之间继承关系。
图中箭头方向志向基对象。
哺乳动物是一种热血、有毛发、用奶哺育幼仔动物;狗是有犬牙、食肉、特定骨骼构造、群居哺乳动物;柯利狗是尖鼻子、身体颜色红白相闻、适合放牧狗。
在继承链中,每个类继承了它前一种类所有特性。
例如,狗具备哺乳动物所有特性,同步还具备区别于其他哺乳动物(如猫、大象等)特性。
图中从下到上继承关系是:
柯利狗是狗,狗是哺乳动物。
“柯利狗”类继承了“狗”类特性,“狗”类继承了“哺乳动物”类特性。
以面向对象程序设计观点来看,继承所表达是对象类之间有关关系。
这种关系使得某类对象可以继承此外一类对象特性和能力。
若类之间具备继承关系.则它们之间具备下列几种特性:
(1)类间具备共享特性(涉及数据和程序代码共享);
(2)类间具备差别或新增某些(涉及非共享数据和程序代码);
(3)类间具备层次构造。
假设有两个类A和B,若类B继承类A,则属于类B中对象具备类A一切特性(涉及数据属性和操作),这时,咱们称被继承类A为基类或父类或超类;而称继承类B为类A派生类或子类。
同步,咱们还可以说,类B是从类A中派生出来。
如果类B从类A派生出来,而类C又是从类B派生出来,就构成了类层次。
这样,咱们又有了直接基类和间接基类概念。
类A是类B直接基类,是类c间接基类。
类c不但继承它直接基类所有特性,还继承它所有间接基类特性。
对于动物继承链,用面向对象程序设计术语,咱们称“哺乳动物”是“狗”基类,“狗”是“哺乳动物”派生类。
“哺乳动物”、“狗”、“柯利狗”构成类层次。
“哺乳动物”是“狗”直接基类,是“柯利狗”间接基类。
如果类B是类A派生类,那么,在构造类B时候,咱们不必重新描述A所有特性,咱们只需让它继承类A特性,然后描述与基类A不同那些特性。
也就是说,类B特性由继承来和新添加两某些特性构成。
详细地说,继承机制容许派生类继承基类数据和操作(即数据成员和成员函数),也就是说,容许派生类使用基类数据和操作。
同步,派生类还可以增长新操作和数据。
例如,子女类可以从父母类继承房子和汽车,固然可以使用房子和汽车,还可以对房子进行再装修。
继承作用有两个:
其一,避免公用代码重复开发,减少代码和数据冗余;
其二,通过增强一致性来减少模块间接口和界面。
继承使程序不再是毫无关系类堆砌,而具备良好构造。
继承机制为程序员们提供了一种组织、构造和重用类手段。
继承使一种类(基类)数据构造和操作被另一种类(派生类)重用,在派生类中只需描述其基类中没有数据和操作。
这样,就避免了公用代码重复开发,增长了程序可重用性,减少了代码和数据冗余。
同步,在描述派生类时,程序员还可以覆盖基类某些操作,或修改和重定义基类中操作,例如子女对所继承房子进行装修。
继承机制以有关关系来组织事物,可以减少咱们对相似事物进行阐明和