C#面向对象的基本概念
“面向对象=对象+类+继承+通信”。如果一个软件系统使用了这样四个概念进行设计和实现,我们就可以认为这个软件系统是面向对象的。
一、一切都是对象
1. 对象概述
对象可以表示几乎所有的实物和概念。比如:一个人、一件事、一辆汽车、一本书、一个文件、一台计算机、一个快捷键、一种语言、一个图形、一种管理方式等都可以表示一个对象。
所有的实物可以表示对象;所有的概念也可以表示对象。就是说,所有的实物、所有的标识、所有的名称、所有的名词、所有的概念等都可以称为对象。
对象是系统中用于描述客观事物的一个实体,它是构成系统的一个基本单位。
?对象的属性是与对象相关的特性和变量;
?对象的操作是对象可以执行的、用于改变其自身或者外部,并且产生了影响的方法、行为和函数。
比如汽车这个对象,它的重量、颜色都可以作为对象的属性,它能够执行的操作可以是行驶、鸣笛等。
2. 提示
对象是具有特殊属性(数据)和行为方式(方法)的实体,是将各种数据和对这些数据进行操作的函数约束在一起的一种语言结构。由于对象包含了数据和方法,因此就像微型的、独立的程序,这样就能把它们构造成程序块,建立更加复杂的对象。
对象由两部分描述:第一部分是它的“数据”,包括对象的特性、状态等静态信息;第二部分是它的“行为(方法)”,包括该对象的操作、功能等能动信息。
3. 消息和方法
怎样要求对象完成指定的操作?对象之间是如何进行联系呢?所有这一切都只能通过传递消息来实现。消息用来请求对象执行某种操作或回答某些信息的要求;消息使数据流和控制流统一起来;某一对象在执行相应的处理时,如果需要,可以通过传递消息请求其它对象完成某些处理工作或回答某些信息;任何对象在执行所要求的操作时,都可以通过传递消息与其它对象联系。因此,程序的执行是靠在对象间传递消息来完成的。
发送消息的对象称为发送者,接收消息的对象称为接收者。一个对象可以接收不同形式、不同内容的多个消息;相同形式的消息可以送往不同的对象;不同的对象对于形式相同的消息可以有不同的解释,能够做出不同的反应。对于传来的消息,对象可以返回相应的回答信息,但这种返回并不是必须的。
可以把全部对象分成各种对象类,每个对象类都定义一组所谓的“方法”,实际上可以把它们看作是作用于该类对象上的各种操作。
因此,面向对象的程序设计方法都可以通过对象及其相互间传递消息来实现。
二、类的面向对象特性
1. 类的概述
类是一组具有相同的数据结构和相同操作的对象的集合。类是对一系列具有相同性质的对象的抽象,是对对象共同特征的描述。
如果每一辆汽车是一个对象的话,那么可以把所有的汽车看做一个模板,模板也就可以称为所有汽车的类。当然,一辆汽车就是这个类的一个对象。
只要定义一个类就可以得到若干个实例(instance)对象。在一个类中,每个对象(object)都是类的实例,当然,类的实例就叫做类的对象,可以使用类中提供的方法。从类定义中产生对象,必须有建立实例的操作,C++和C#中的new操作符可用于建立一个类的实例,C#提供的方法则更加安全。
因为类描述了具有共同特性(数据)和行为(方法)的对象集合,所以一个类实际上就是一种对象类型,它描述了属于该类型的所有对象的性质。比如,所有的整型数都具有相同的特性和行为集合。
对象是在执行过程中由其所属的类动态生成的。一个类可以生成多个不同的对象,而一个类的所有对象具有相同的性质,即其外部特性和内部实现都是相同的,一个对象的内部状态只能由其自身来修改,任何别的对象都不能改变它。因此,同一个类的对象虽然在表现形式上相同,但它们可以有不同的内部状态,这些对象并不是完全一样的。
2. 类的特性
类的定义决定了类具有以下3个特性:封装性、继承性和多态性。
1)封装性
封装是将数据和加工该数据的方法(函数)封装为一个整体,使用户只能见到对象的外特性(对象能接收哪些消息,具有哪些处理能力),而不能看到对象的内特性(保存内部状态的私有数据和实现加工能力的算法)。因为对象的内特性对用户来说是隐藏的,
封装的目的在于把对象的设计者和对象的使用者区分开,使用者不需要知道行为实现的细节,只需要使用设计者提供的消息来访问该对象就行了。
封装的概念与集成电路芯片类似,用陶瓷封装起来的一块集成电路芯片,其内部电路是不可见的,而且使用者也不必关心它的内部结构,只关心芯片引脚的个数、引脚的电气参数以及引脚提供的功能就行了。利用这些引脚,使用都将各种不同的芯片连接起来,就能组装成具有一定功能的产品。
封装具有以下的特征:
?一个清楚的边界,所有对象的内部变化范围限制在这个边界内。
?一个接口,用来描述对象本身与其它对象之间的相互作用。
?受保护的内部实现,它给出了由软件对象提供的功能细节,在外部不能访问这些细节。
面向对象的语言以对象协议或规格说明作为对象的外部界面。协议指明该对象所能接收的消息,在对象的内部,每个消息响应一个方法,方法实施对数据的操作。对数据方法的描述是协议的实现部分。
2)继承性
继承(Inheritance)是指一个类获取另一个类的性质的过程。已经存在的类所声明的数据和新类所增加的声明的组合,就可以定义一个新类了。新类重复使用已经存在的类的定义,而不会要求修改该类。已经存在的类可以作为基类进行引用,而新类可以作为派生类进行引用。这种复用技术大大降低了软件的开发周期。
比如,汽车这个类已经存在,作为具有自身特征的卡车就可以从汽车类中继承。它同汽车一样,具有颜色、重量这些特征,可以驾驶和鸣笛等;它还具有一般汽车不一定具备的特征,如可以载货等。
一个类的上层可以有父类(或超类),下层可以有子类,形成一种层次结构。如下所示:
Class1
↓
Class2
↓
Class3
这种层次结构具有继承性:一个类继承其父类的描述。这种继承具有传递性,即如果类Class2继承Class1,而Class3继承Class2,则Class3继承Class1。其中Class2对Class1、Class3对Class2的继承叫做直接继承,而Class3对Class1的继承叫做间接继承。一个类实际上继承了层次结构中在其上面的类的描述,因此,属于某个类的对象除具有该类所描述的特性外,还具有层次结构中该类上层各类所描述的性质。
在类的层次结构中,一个类可以有多个子类,也可以有多个基类(即父类和超类)。因此,一个类可以直接继承多个类,这种继承方式称为多重继承。如果一个类最多只能有一个基类,则它最多只能直接继承一个类,这种继承方式称为简单继承或单重继承。
3)多态性
多态性(Polymorphism)是指一个名字可以具有多种语义。在面向对象的程序设计语言中,多态引用表示可以引用多个类的实例。假如类B是派生类D的基类,则在使用基类B的对象b的地方也可以使用派生类D的对象d。这意味着,当同样的消息可以被送到一个基类的对象和它所派生类的对象上时,这就是多态性。
比如有一个类层次,用来执行收集数据的操作,它的基类可以收集一个人的姓名、年龄、参加工作时间、住址、邮政编码等,其派生类可以根据职业的不同确定增加什么辅助信息,比如,管理人员可能要增加职务、所在部门等信息,而工人可能要增加工程、技术级别等信息。也就是说,基类收集所有派生类都需要的通用信息,而派生类收集与具体工作任务相关的附加信息。利用多态性,可以把收集公共数据的信息送往每个类,而基类和派生类以一种合适的方式响应这些信息。
在运行时,通过指向基类的指针,可以调用实现派生类中的方法。把一些对象放到一个数组中。这些对象不必是相同类型的对象。然后调用它们的方法。此时,多态性的作用就体现出来了。当然,如果它们都从某个类开始继承,那么可以把这些派生类都放到一个数组中。如果这些对象都有同名方法,就可以调用每个对象的同名方法。
三、面向对象与面向过程
1. 面向对象
面向对象就是把数据和对数据的操作方法存放在一起,作为一个整体——对象。对同一类对象抽象出它的共同特性,以形成类。类中的大部分数据,只能用本类的方法进行处理。类通过一个简单的外部接口与外界发生联系,对象与对象之间通过消息进行通信。程序流程由用户在程序设计中自行决定。
简单地说,面向对象,就是把同类问题进行打包,可以随时调用。
2. 面向过程
面向过程就是自顶向下顺序执行,逐步求精。其程序结构是按功能划分为若干个基本模块,这些模块形成一个树状结构;每一模块内部都是由顺序、选择和循环三种基本结构组成;各模块之间在功能上相对独立,它们的关系尽可能简单;而模块化是使用子程序的方法来实现的。程序流程在书写程序时就已决定。
简单地说,面向过程,就是一步一步按顺序执行,不能打乱执行过程的先后顺序。
虽然说,面向对象的编程方法已经成为目前最流行的软件开发方法,但是,并不是说面向对象的程序设计方法一定会比面向过程的方法或其它的程序设计方法要好。因为,每一种编程方法都有自己的一套理论框架,也有自己相应的设计、分析和建模的方法,所以它们都有各自的优点和缺点。选择的依据主要是看目标系统所要解决的是哪种类型的问题。比如,对于工程计算,面向过程的方法就可能比面向对象的方法更加合适;如果解决逻辑推理、机器证明等人工智能方面的问题,可能就需要采用面向逻辑的技术和方法;如果是设计知识库和专家系统,还可以选择面向规则的程序设计技术。