第八讲面向对象程序设计前述各讲中,侧重介绍了C#语言的过程化的基本语法规格和使用方法,而没有提到在所有程序代码中都使用的一个关键字——class。实际上,C#程序代码都是由class——类来封装组织的,本章正式介绍有关类的概念以及如何使用类来构造一个更复杂的应用程序。类是C#语言实现面向对象程序设计的基础,是构成C#程序的基本单元,类把对象、属性和方法这些类成员封装在一起构成一个有机整体,即数据结构。通过本章的学习,要求掌握定义类和成员的方法,掌握访问成员方法的方式,理解被保护数据如何屏蔽外部访问的原理,从而更深入的理解类的封装性,体会面向对象程序设计的思想。本章学习重点:理解面向对象程序设计的思想和基本概念。掌握创建并初始化类的实例的方法。掌握定义、访问类成员的方法。掌握构造函数和析构函数的定义和使用方法。掌握定义和使用静态成员及实例成员的区别。掌握重载方法、运算符的概念和使用方法。理解类的封装性原理及实施机制(访问修饰符)。一、面向对象程序设计思想传统的结构化程序编程(如C语言)是先设计一组函数,即解决问题的算法,然后针对问题要处理的数据特征找出相应的数据存储方法,即数据结构。这就是Pascal语言设计者——Nicholase.Wirth提出的著名公式:程序=算法+数据结构;这种编程的特征是先从算法入手,然后才考虑数据结构。算法和数据结构是相互独立的部分。存在如下的缺点:当描述事物的数据结构发生了改变,所有与该数据结构相关的语句、过程和函数都要重新设计。功能和数据分离,不符合人们对现实世界的认识,要使数据与程序始终保持相容,已成为程序员开发的一个沉重负担;安全性差;代码可重用性差,难以维护。为了解决结构化程序设计的这些问题,面向对象的技术应运而生。它是一种非常强有力的软件开发方法。将数据和对数据的操作作为一个互相依赖、不可分割的整体,采用数据抽象和信息屏蔽技术,力图使对现实世界问题的求解简单化。1、面向对象(Object-orientedProgramming)的基本概念程序=对象+类+继承+通信对象(object):对象是面向对象开发的基本成分。每个对象可用它本身的一组属性和其上的一组操作来定义。对象可以是现实世界的一个物理对象,还可以是某一类概念实体的实例。比如,一个汽车,一个人,一本书,乃至一种语言,一个图形,一种管理方法都可以作为一个对象。从分析和设计的角度来看,对象把有关的现实世界的实体模型化。比如对某辆汽车这个对象,它的重量、颜色都可以作为对象的属性,它可以执行的操作可以是行驶、鸣笛等。类(Class):类是一组具有相同数据结构和相同操作的对象的集合。类是对一系列具有相同性质对象的抽象,是对对象共同特征的描述。比如每一辆汽车是一个对象的话,所有的汽车可以作为一个模板,我们就可以定义汽车这个类。在一个类中,每个对象都是这个类的实例。可以使用类提供的方法。从类定义中产生对象,必须有建立实例的操作,使用new运算符可以建立一个实例。继承(inheritance):继承是根据已经存在的类作为基础建立新类的机制。例如汽车作为一个类存在,作为拥有汽车特征的卡车可以从汽车类中继承。它同汽车一样,具有颜色、重量等特征,可以行驶和鸣笛。同时,卡车还具有一般汽车不具备的功能,如载货等。二、类“类”用来描述具有相同数据结构和特性的“一组对象”,可以说,“类”是对“对象”的抽象,而“对象”是“类”的具体实例,即一个类中的对象具有相同的型,但每个对象具有各不相同的值。在C#中对象的类型为“类”(class),总是先定义一个“类”,然后用该类去定义若干个同类型的对象。类的定义方法:class类名{//类的成员定义}其中:类名必须是合法的C#标识符,一般应给一个有意义的名称。类名的首字母一般用大写字母表示,以示与对象名的区别;类的成员定义包括对这个类的属性和方法的定义,该项可选。以上是用户自定义类的语句格式。在.NET框架中包含了大量的系统内置的类,如前面使用的Console类。这个类包含了多个数据成员和方法成员代码,如WriteLine()和Write()方法。usingSystem;classProgram{publicstaticvoidMain(){}}classCar{}注:一个程序可以包含若干个类;一个项目包含多个C#文件,有且只有一个主方法:如publicstaticvoidMain(){}类的成员:类由数据成员和函数成员组成,它们分别是面向对象理论中类的属性和方法。类的数据成员包含类的常量成员和类的变量成员,它们可以是前面介绍的任何数据类型的变量,甚至可以是其他类。包含有可执行代码的成员被认为是类的函数成员。这些函数成员包括:方法成员(method)构造函数(constructor)析构函数(destructor)属性成员(property)索引成员(indexer)运算符成员(operator)事件成员(event)usingSystem;classProgram{publicstaticvoidMain(){CarcarNum0=newCar();}}classCar{privateconstintwheel=4;publicintweight;//汽车重量publicintcolor;//汽车颜色publicstringname;//汽车名字publicstringstyle;//汽车车型publicvoidbeep()//汽车鸣笛{Console.WriteLine(Beep...!);}publicvoidrun()//汽车行驶{Console.WriteLine(NowThecarisrunning!);}}四个数据成员和两个函数成员派生类:如果一个类是由另一个类派生的,或者说一个类是从另一个类继承而来的,称为子类,的格式为:Class类名:基类名{//类的成员定义}将在下一讲中涉及。类成员的访问权限:在编写程序时,我们可以对类的成员使用不同的访问修饰符,从而定义它们的访问级别:公有成员C#中的公有成员允许类的使用者从外部进行访问。公有成员的修饰符为public。这是限制最少的一种访问方式。私有成员私有成员仅限于类中的成员可以访问。从类的外部访问私有成员是不合法的。如果在声明中没有出现成员的修饰符,按照默认方式成员为私有。私有成员的修饰符为private。保护成员为了方便派生类的访问,同时又希望成员对于外界是隐藏的,可以是用protected修饰符,声明成员为保护成员。内部成员使用internal修饰符的类的成员是一种特殊的成员。该类成员允许同一个命名空间中的类访问。三、创建类的对象类是一种用于创建对象的定义,它本身并不能存储信息或执行代码。而对象是类的一个实例,它可以类定义的框架来存储信息和执行代码。所以定义类后,便可以创建对象。创建类对象的过程就是实例化类。语句格式如下:类名对象名=new类名();usingSystem;classProgram{publicstaticvoidMain(){CarcarNum0=newCar();//可以创建无数个属于类的对象}}classCar{privateconstintwheel=4;//只能在Car这个类中被访问publicintweight;//汽车重量publicintcolor;//汽车颜色publicstringname;//汽车名字publicstringstyle;//汽车车型publicvoidbeep()//汽车鸣笛{Console.WriteLine(Beep...!);}publicvoidrun()//汽车行驶{Console.WriteLine(NowThecarisrunning!);}}四、类的数据成员类数据成员是用来描述一个类的特征即面向对象理论中的类的属性。C#中有两类数据成员,一类是常量成员,一类是变量成员(字段成员)。常量成员:在某个类中定义的常量就是这个类的常量成员。这个类中所有的其他成员都可以使用这个常量。在一个类中定义常量的基本格式如下:class类名{【常量修饰符】const数据类型常量名1=常量表达式1,常量名2=常量表达式2.。。。;}常量修饰符为可选择项。修饰符包括new、private、protected、internal和public。new修饰符用于在子类覆盖父类同名的标识符。其他修饰符规定了常量成员的访问权限。“数据类型”在此次为值类型,因为这里定义常量。“常量表达式”中只允许出现常量,不能出现变量。访问常量成员:通过以下成员访问一个类中具有public访问权限的常量成员:类名.常量成员名usingSystem;classClassA{publicconstintvar1=10,var2=20;}classClassB{publicconstintvar3=ClassA.var1+ClassA.var2;}classPromgram{publicstaticvoidMain(){}}思考:将类ClassA中的public改为private会有什么样的结果。程序不能执行,ClassA不能在外部被访问classClass1{protectedconstfloatPI=3.1415926;publicconstfloatsquare=PI*PI;publicconstintn=100;}在类Class1的外部可以访问常量square和n,但是不能访问常量PI。由于常量square定义在Class1的内部,所以square可以访问常量PI。变量成员:在类中定义的变量为该类的变量成员。变量成员同常量成员是不同的。如果类的实例(对象)不存在,即没有创建该类的对象,则表示没有使用变量的需求,此时系统不会为这个类的变量成员分配存储空间,变量成员无法为访问。只有在生成类的对象(实例)后,变量成员才在这个对象所占用的空间中得到自己的存储空间。所以变量成员通常属于一个特定的对象,而常量成员属于类本身。1、定义变量成员:Class类名{[变量修饰符]数据类型变量名1,变量名2….;}其中:[变量修饰符]有new、private、public、internal、protected、static(静态)和readonly(只读)。修饰符private、protected、public和internal代表一个变量的访问权限。static修饰符将一个变量成员指定为静态成员,这样该变量成员就如同常量成员一样,属于类本身,而不属于特定的类的对象。可以使用“类名.静态成员名”的格式进行直接访问,而无需生成对象。readonly修饰规定了一个变量的读写权限。用readonly修饰的变量成员只能读,不能写,即除了赋初值外,在程序的任何一个部分都无法改变这个变量成员的值。(变量赋初值和构造函数中可以修改readonly变量成员值)Static和readonly修饰符可以与其他修饰符组合使用。classCar{privateconstintwheel=4;publicintweight;//汽车重量publicintcolor;//汽车颜色publicstringname;//汽车名字publicstringstyle;//汽车车型publicvoidbeep()//汽车鸣笛{Console.WriteLine(Beep...!);}publicvoidrun()//汽车行驶{Console.WriteLine(NowThecarisrunning!);}}如果定义的变量成员为引用类型,则需要使用new运算符生成实例的存储空间。实现格式如下:ClassClassApp{[变量修饰符]类名变量名=new类名();//创建一个对象}如:在类ClassE中定义一个ClassA的实例作为变量成员:classClassE{intm,n;//int为值类型,直接生成实例Carx=newCar();//Car为引用类型,需要使用new运算符生成实例。}2、变量成员的初始化在应用中,变量成员分为两种: