《C程序设计 第二章 面向对象程序设计.ppt》由会员分享,可在线阅读,更多相关《C程序设计 第二章 面向对象程序设计.ppt(63页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、C#程序设计与案例教程清华大学出版社第二章第二章面向对象程序设计面向对象程序设计C#.NETC#.NET是一种面向对象的程序设计语言,它是一种面向对象的程序设计语言,它支持面向对象程序设计的许多新特性。面向支持面向对象程序设计的许多新特性。面向对象编程主要思想是将数据以及处理这些数对象编程主要思想是将数据以及处理这些数据的相应方法封装到类中,使用类创建的实据的相应方法封装到类中,使用类创建的实例称为对象。类类型支持继承,派生的类可例称为对象。类类型支持继承,派生的类可以对基类进行扩展和特殊化。以对基类进行扩展和特殊化。1 1版权所有版权所有C#程序设计与案例教程清华大学出版社第二章第二章面向对
2、象程序设计面向对象程序设计C#.NET是一种面向对象的程序设计语言,它支持面向对象程序设计的许多新特性。面向对象编程主要思想是将数据以及处理这些数据的相应方法封装到类中,使用类创建的实例称为对象。类类型支持继承,派生的类可以对基类进行扩展和特殊化。2 2版权所有版权所有C#程序设计与案例教程清华大学出版社第二章第二章面向对象程序设计面向对象程序设计C#.NET是一种面向对象的程序设计语言,它支持面向对象程序设计的许多新特性。面向对象编程主要思想是将数据以及处理这些数据的相应方法封装到类中,使用类创建的实例称为对象。类类型支持继承,派生的类可以对基类进行扩展和特殊化。3 3版权所有版权所有C#程
3、序设计与案例教程清华大学出版社目录面向对象的基本思想类与对象类的方法与重载域、属性和索引继承与多态抽象类与接口委托与事件4 4版权所有版权所有C#程序设计与案例教程清华大学出版社2.1面向对象的基本思想面向对象是一种新兴的程序设计方法,或者是一种新的程序设计规范,其基本思想是使用对象、类、继承、封装、消息等基本概念来进行程序设计;从现实世界中客观存在的事物(即对象)出发来构造软件系统,并且在系统构造中尽可能运用人类的自然思维方式。5 5版权所有版权所有C#程序设计与案例教程清华大学出版社1 1对象的基本概念对象的基本概念对象的基本概念对象的基本概念对象是系统中用来描述客观事物的一个实体,它对象
4、是系统中用来描述客观事物的一个实体,它是构成系统的一个基本单位。是构成系统的一个基本单位。2 2类类类类把众多的事物归纳、划分成一些类是人类在认识把众多的事物归纳、划分成一些类是人类在认识客观世界时经常采用的思维方法。分类的原则是客观世界时经常采用的思维方法。分类的原则是抽象。类是具有相同属性和服务的一组对象的集抽象。类是具有相同属性和服务的一组对象的集合,它为属于该类的所有对象提供了统一的抽象合,它为属于该类的所有对象提供了统一的抽象描述,其内部包括属性和服务两个主要部分。描述,其内部包括属性和服务两个主要部分。6 6版权所有版权所有C#程序设计与案例教程清华大学出版社3面向对象的基本特征面
5、向对象的基本特征(1)封装性(2)继承性(3)多态性7 7版权所有版权所有C#程序设计与案例教程清华大学出版社2.2类与对象类与对象类和对象是面向对象的程序设计语言的核心和本质。类实际上定义了一种崭新的数据类型。定义了类之后,就可以使用这种新的数据类型创建对象。类是对象的模板,对象是类的实例。使用类的好处在于,它有利于程序的模块化设计和开发,可以隐藏内部的实现细节,并能增强程序代码的重用性。8 8版权所有版权所有C#程序设计与案例教程清华大学出版社2.2.1类的定义类使用类使用classclass关键字声明。采用的形式为:关键字声明。采用的形式为:类修饰符类修饰符类修饰符类修饰符classcl
6、ass类名称类名称类名称类名称:基类以及实现的接口基类以及实现的接口基类以及实现的接口基类以及实现的接口列表列表列表列表类体类体类体类体;9 9版权所有版权所有C#程序设计与案例教程清华大学出版社publicclassPersonpublicclassPerson privatestringname;privatestringname;privatecharsex;privatecharsex;privateprivateintintage;age;publicpublicPerson(stringPerson(string n,charn,char s,ints,inta)a)name=n;
7、name=n;sex=s;sex=s;age=a;age=a;publicvoidDisplay()publicvoidDisplay()Console.WriteLine(“name:0”,name);Console.WriteLine(“name:0”,name);Console.WriteLine(“sex:0”,sex);Console.WriteLine(“sex:0”,sex);Console.WriteLine(“age:0”,age);Console.WriteLine(“age:0”,age);1010版权所有版权所有C#程序设计与案例教程清华大学出版社2.1.2类的成员1类
8、的成员分类 n n常量:表示与该类相关联的常量值。常量:表示与该类相关联的常量值。n n字段:即该类的变量。字段:即该类的变量。n n类型:用于表示一些类型,它们是该类的局部类型。类型:用于表示一些类型,它们是该类的局部类型。n n方法:用于实现可由该类执行的计算和操作。方法:用于实现可由该类执行的计算和操作。n n属性:用于定义一些命名特性,通过它来读取和写入相关的特性。属性:用于定义一些命名特性,通过它来读取和写入相关的特性。n n事件:用于定义可由该类生成的通知。事件:用于定义可由该类生成的通知。n n索引器:使该类的实例可按与数组相同的(语法)方式进行索引。索引器:使该类的实例可按与数
9、组相同的(语法)方式进行索引。n n运算符:用于定义表达式运算符,通过它对该类的实例进行运算。运算符:用于定义表达式运算符,通过它对该类的实例进行运算。n n实例构造函数:用于规定在初始化该类的实例时需要做些什么。实例构造函数:用于规定在初始化该类的实例时需要做些什么。n n析构函数:用于规定在永久地放弃该类的一个实例之前需要做些什么。析构函数:用于规定在永久地放弃该类的一个实例之前需要做些什么。n n静态构造函数:用于规定在初始化该类自身时需要做些什么。静态构造函数:用于规定在初始化该类自身时需要做些什么。1111版权所有版权所有C#程序设计与案例教程清华大学出版社2类成员的可访问性类成员的
10、可访问性1212版权所有版权所有C#程序设计与案例教程清华大学出版社3.静态成员与实例成员静态成员与实例成员 C#C#的类定义中可以包含两种成员:静态成员和的类定义中可以包含两种成员:静态成员和的类定义中可以包含两种成员:静态成员和的类定义中可以包含两种成员:静态成员和非静态成员(也即实例成员)。使用了非静态成员(也即实例成员)。使用了非静态成员(也即实例成员)。使用了非静态成员(也即实例成员)。使用了staticstatic修饰符的方法为静态成员,反之则是实例成员。修饰符的方法为静态成员,反之则是实例成员。修饰符的方法为静态成员,反之则是实例成员。修饰符的方法为静态成员,反之则是实例成员。1
11、313版权所有版权所有C#程序设计与案例教程清华大学出版社(1 1)使用)使用staticstatic修饰符声明属于类型本身而不是属修饰符声明属于类型本身而不是属于特定对象的静态成员。于特定对象的静态成员。staticstatic修饰符可用于字段、修饰符可用于字段、方法、属性、运算符、事件和构造函数,但不能方法、属性、运算符、事件和构造函数,但不能用于索引器、析构函数或类型。用于索引器、析构函数或类型。(2 2)静态成员属于类,在内存中只有一份,不必建)静态成员属于类,在内存中只有一份,不必建立该类的实例,通过类名即可使用;而实例成员立该类的实例,通过类名即可使用;而实例成员属于用该类创建的实
12、例,要通过对象名使用。属于用该类创建的实例,要通过对象名使用。(3 3)非静态方法可以访问类中包括静态方法在内的)非静态方法可以访问类中包括静态方法在内的所有成员,而静态方法只能访问类中的静态成员。所有成员,而静态方法只能访问类中的静态成员。1414版权所有版权所有C#程序设计与案例教程清华大学出版社【案例案例2-1】雇员类。该示例读取新雇员的名称和ID,逐个增加雇员计数器并显示新雇员的有关信息以及新的雇员数。为简单起见,该程序从键盘读取当前的雇员数。1515版权所有版权所有C#程序设计与案例教程清华大学出版社2.1.3创建对象与构造函数类声明后,可以创建类的实例,即对象。创建类类声明后,可以
13、创建类的实例,即对象。创建类的实例需要使用的实例需要使用newnew关键字。类的实例相当于关键字。类的实例相当于一个变量,创建类实例的格式如下:一个变量,创建类实例的格式如下:类名类名 对象名对象名=newnew构造函数(参数类表)构造函数(参数类表);例如:例如:PointPointmyPointmyPoint=newPoint();=newPoint();1616版权所有版权所有C#程序设计与案例教程清华大学出版社创建新对象时将调用类的构造函数。构造函数主要用来为对象分配存储空间,完成初试化操作(如给类的成员赋值等)。在C#中,类的构造函数遵循以下规定:(1)构造函数的函数名与类的名称一样
14、。(2)一个类可以有多个构造函数。(3)如果类没有构造函数,将自动生成一个默认的无参数构造函数,并使用默认值初始化对象的字段(例如,int将初始化为0)。1717版权所有版权所有C#程序设计与案例教程清华大学出版社(4 4)类的构造函数可通过初始值设定项来调用基类)类的构造函数可通过初始值设定项来调用基类的构造函数,例如:的构造函数,例如:publicpublicStudent(stringStudent(stringno,stringno,stringname,charname,char sex,intsex,intage)age):base(namebase(name,sex,agesex
15、,age)(5 5)类的构造函数也可通过关键字)类的构造函数也可通过关键字thisthis调用同一个调用同一个类的另一个构造函数,例如:类的另一个构造函数,例如:publicPoint():this(0,20)publicPoint():this(0,20)1818版权所有版权所有C#程序设计与案例教程清华大学出版社【案例案例2-2】Point类。定义一个点类Point,建立对象并显示点对。1919版权所有版权所有C#程序设计与案例教程清华大学出版社2.3类的方法与重载类的方法与重载2.3.1方法的定义在在C#C#中,数据和操作均封装在类中,数据是以中,数据和操作均封装在类中,数据是以成员变量
16、的形式出现,而操作主要体现在方法成员变量的形式出现,而操作主要体现在方法的使用上。的使用上。在类中,方法的一般格式为:在类中,方法的一般格式为:方法修饰符方法修饰符返回值类型返回值类型 方法名(方法名(参数列表参数列表)方法体方法体 2020版权所有版权所有C#程序设计与案例教程清华大学出版社2.3.22.3.2方法的参数类型方法的参数类型C#C#方法的参数有四种类型:值参数、引用参数、输方法的参数有四种类型:值参数、引用参数、输出参数和参数数组。出参数和参数数组。未用任何修饰符声明的参数为值参数。值参数在调未用任何修饰符声明的参数为值参数。值参数在调用该参数所属的函数成员(方法、实例构造函数
17、、用该参数所属的函数成员(方法、实例构造函数、访问器和运算符)时创建,并用调用中给定的实访问器和运算符)时创建,并用调用中给定的实参值初始化。当从该函数返回时值参数被销毁。参值初始化。当从该函数返回时值参数被销毁。对值参数的修改不会影响到原自变量。值参数通对值参数的修改不会影响到原自变量。值参数通过复制原自变量的值来初始化。过复制原自变量的值来初始化。2121版权所有版权所有C#程序设计与案例教程清华大学出版社用params修饰符声明的变量称为参数数组,它允许向函数传递个数变化的参数。在方法的参数类表中只允许出现一个参数数组,而且在方法同时具有固定参数和参数数组的情况下,参数数组必须放在整个参
18、数列表的最后,同时参数数组只允许是一维数组。不能将params修饰符与ref和out修饰符组合起来使用。2222版权所有版权所有C#程序设计与案例教程清华大学出版社用用refref修饰符声明的参数为引用参数。引用参数就是修饰符声明的参数为引用参数。引用参数就是调用者提供的自变量的别名。引用参数并不定义调用者提供的自变量的别名。引用参数并不定义自的变量,而是直接引用原自变量,因此对引用自的变量,而是直接引用原自变量,因此对引用参数的修改就将直接影响相应自变量的值。在函参数的修改就将直接影响相应自变量的值。在函数调用中,引用参数必须被赋初值。数调用中,引用参数必须被赋初值。用用outout修饰符定
19、义的参数称为输出参数。如果希望函修饰符定义的参数称为输出参数。如果希望函数返回多个值,可使用输出参数。输出参数与引数返回多个值,可使用输出参数。输出参数与引用参数类似,它并不定义自己的变量,而是直接用参数类似,它并不定义自己的变量,而是直接引用原变量,这样当在函数内为输出参数赋值时,引用原变量,这样当在函数内为输出参数赋值时,就相当于给原自变量赋值。与引用参数的差别在就相当于给原自变量赋值。与引用参数的差别在于:输出参数在调用方法前无需对变量进行初始于:输出参数在调用方法前无需对变量进行初始化。化。2323版权所有版权所有C#程序设计与案例教程清华大学出版社【案例案例2-3】演示方法参数。本案
20、例演示方法的四类参数。2424版权所有版权所有C#程序设计与案例教程清华大学出版社2.3.3静态方法和实例方法n n类的方法前加了类的方法前加了staticstatic关键字,则该方法为静态关键字,则该方法为静态方法,反之为实例方法。静态方法为类所有,方法,反之为实例方法。静态方法为类所有,可以通过对象来使用,也可以通过类来使用。可以通过对象来使用,也可以通过类来使用。但一般提倡通过类名来使用,因为静态方法只但一般提倡通过类名来使用,因为静态方法只要定义了类,不需用建立类的实例就可使用。要定义了类,不需用建立类的实例就可使用。静态方法只能使用类的静态成员。静态方法只能使用类的静态成员。n n实
21、例方法必须通过类的实例来使用。实例方法实例方法必须通过类的实例来使用。实例方法可以使用类的非静态成员,也可以使用类的静可以使用类的非静态成员,也可以使用类的静态成员。态成员。2525版权所有版权所有C#程序设计与案例教程清华大学出版社【案例案例2-4】演示静态方法和实例方法。2626版权所有版权所有C#程序设计与案例教程清华大学出版社2.3.4方法重载类中两个以上的方法(包括隐藏的继承而来的方法)取的名字相同,只要使用的参数类型或者参数个数不同,编译器便知道在何种情况下应该调用哪个方法,这就叫做方法的重载。2727版权所有版权所有C#程序设计与案例教程清华大学出版社【案例案例2-5】方法重载。
22、本案例定义了一个OverTest类。在该类中,重载了Area方法。2828版权所有版权所有C#程序设计与案例教程清华大学出版社2.3.5运算符重栽运算符也是运算符也是C#C#类的一个重要成员,系统对大类的一个重要成员,系统对大部分运算符都给出了常规定义,这些定义大部部分运算符都给出了常规定义,这些定义大部分和现实生活中这些运算符的意义相同。但可分和现实生活中这些运算符的意义相同。但可以根据需要给这些运算符赋予一个新的含义,以根据需要给这些运算符赋予一个新的含义,这就是这就是运运运运算符重载。运算符重载允许为运算指算符重载。运算符重载允许为运算指定用户定义的运算符实现,其中一个或两个操定用户定义
23、的运算符实现,其中一个或两个操作数是用户定义的类或结构类型。作数是用户定义的类或结构类型。C#C#中运算中运算符重载的基本格式如下:符重载的基本格式如下:返回值类型返回值类型 operatoroperator 运算符(运算对象列表)运算符(运算对象列表)重载的实现部分;重载的实现部分;2929版权所有版权所有C#程序设计与案例教程清华大学出版社【案例案例2-6】复数类。本案例定义了一个复数类,展示了如何使用运算符重载复数加法运算。3030版权所有版权所有C#程序设计与案例教程清华大学出版社2.3.6this关键字thisthis关键字引用类的当前对象,成员通过关键字引用类的当前对象,成员通过t
24、histhis关关键字可以知道自己属于哪一个实例。键字可以知道自己属于哪一个实例。thisthis关键关键字是一个隐含引用,它隐含于每个类的成员函字是一个隐含引用,它隐含于每个类的成员函数中。但需要注意的是静态函数没有数中。但需要注意的是静态函数没有thisthis关键关键字。字。thisthis关键字可用于从构造函数、实例方法关键字可用于从构造函数、实例方法和实例访问器中访问成员。和实例访问器中访问成员。3131版权所有版权所有C#程序设计与案例教程清华大学出版社以下是以下是thisthis的常用用途。的常用用途。(1 1)限定被相似的名称隐含的成员,例如:)限定被相似的名称隐含的成员,例如
25、:publicpublicEmployee(stringEmployee(string name,stirngname,stirngalias)alias)this.namethis.name=name;=name;this.aliasthis.alias=alias;=alias;(2 2)将对象作为参数传递到其他方法,例如:)将对象作为参数传递到其他方法,例如:CalcTax(thisCalcTax(this););(3 3)声明索引器,例如:)声明索引器,例如:publicpublicintint thisintthisintindexindex getreturngetreturnar
26、rayindexarrayindex;setsetarrayindexarrayindex=value;=value;3232版权所有版权所有C#程序设计与案例教程清华大学出版社2.4域、属性和索引2.4.1域域又称字段,它是类的一个成员,这个成员代表域又称字段,它是类的一个成员,这个成员代表与对象或类相关的变量。一个域相当于与对象或类相关的变量。一个域相当于C+C+类类中的简单成员变量。域的声明格式为:中的简单成员变量。域的声明格式为:域修饰符域修饰符 域类型域类型 域名域名;与变量定义一样,域也可以在定义的时候赋初值,与变量定义一样,域也可以在定义的时候赋初值,如:如:stringmode
27、l=Nisan;stringmodel=Nisan;域修饰符可以是域修饰符可以是newnew、publicpublic、protectedprotected、internalinternal、privateprivate、staticstatic、readonlyreadonly等。等。3333版权所有版权所有C#程序设计与案例教程清华大学出版社2.4.2属性 属性是对现实世界中实体特征的抽象,它提供属性是对现实世界中实体特征的抽象,它提供了一种对类或对象特征进行访问的机制。例如:了一种对类或对象特征进行访问的机制。例如:字体、颜色、标题等都可以作为属性。属性所字体、颜色、标题等都可以作为属性
28、。属性所描述的是状态信息,在类的某个实例中,属性描述的是状态信息,在类的某个实例中,属性的值表示该对象相应的状态值。与域相比,属的值表示该对象相应的状态值。与域相比,属性具有良好的封装性。属性不允许直接操作数性具有良好的封装性。属性不允许直接操作数据内容,而是通过访问器进行访问。这种机制据内容,而是通过访问器进行访问。这种机制可以把读取和写入对象的某些特性与一些操作可以把读取和写入对象的某些特性与一些操作关联起来;甚至,它们还可以对此特性进行计关联起来;甚至,它们还可以对此特性进行计算。算。3434版权所有版权所有C#程序设计与案例教程清华大学出版社定义属性的格式如下:访问修饰符属性类型属性名
29、getset3535版权所有版权所有C#程序设计与案例教程清华大学出版社usingSystem;usingSystem;classWindowclassWindowprivatedoubleprivatedoublem_widthm_width=30;=30;publicdoubleWidthpublicdoubleWidthgetreturngetreturnm_widthm_width;setsetm_widthm_width=value;=value;publicstaticvoidMain()publicstaticvoidMain()Windoww=newWindow();Windo
30、ww=newWindow();w.Widthw.Width=20;=20;Console.WriteLine(“TheConsole.WriteLine(“Thewidthofwindowis0.”,w.Width);widthofwindowis0.”,w.Width);3636版权所有版权所有C#程序设计与案例教程清华大学出版社 可以说,属性是一种特殊的方法,但属性和方可以说,属性是一种特殊的方法,但属性和方法也有不同之处,主要有:法也有不同之处,主要有:(1 1)属性不必使用圆括号,但方法一定使用圆)属性不必使用圆括号,但方法一定使用圆括号。括号。(2 2)属性不能制定参数,方法可以指定
31、参数。)属性不能制定参数,方法可以指定参数。(3 3)属性不能使用)属性不能使用voidvoid类型,方法则可以使用类型,方法则可以使用voidvoid类型。类型。3737版权所有版权所有C#程序设计与案例教程清华大学出版社2.4.3索引器索引器允许类或结构的实例按照与数组相同的方索引器允许类或结构的实例按照与数组相同的方式进行索引。索引器类似于属性,不同的是索式进行索引。索引器类似于属性,不同的是索引器包含参数。引器包含参数。定义索引的方式和定义属性非常类似,主要有两定义索引的方式和定义属性非常类似,主要有两部分:部分:使用使用thisthis关键字。关键字。定义一个索引值。定义一个索引值。
32、3838版权所有版权所有C#程序设计与案例教程清华大学出版社【案例案例2-7】带索引的类。本案例说明如何声明私有数组字段myArray和索引器。通过使用索引器可直接访问实例bi。3939版权所有版权所有C#程序设计与案例教程清华大学出版社2.5继承与多态继承与多态继承是面向对象程序设计的一个重要特征,它允许在现有类的基础上创建新类,新类从现有类中继承类成员,而且可以重新定义或加进新的成员,从而形成类的层次或等级。一般称被继承的类为基类或父类,而继承后产生的类为派生类或子类。4040版权所有版权所有C#程序设计与案例教程清华大学出版社2.5.1派生类的声明派生类的声明格式为:派生类的声明格式为:
33、类修饰符类修饰符 classclass派生类类名派生类类名:基类类名基类类名 类体类体 在类的声明中,通过在类名的后面加上冒号和基在类的声明中,通过在类名的后面加上冒号和基类名表示继承。类名表示继承。4141版权所有版权所有C#程序设计与案例教程清华大学出版社【案例案例2-8】派生类的实例。从Person类派生一个新类Employee。4242版权所有版权所有C#程序设计与案例教程清华大学出版社2.5.2多态性多态性多态性是指不同的对象收到相同的消息时,会产生不同动作。从而实现“一个接口,多个方法”。它允许以相似的方式来对待所有的派生类,尽管这些派生类是各不相同的。C#支持两种类型的多态性:(
34、1 1)编译时的多态性是通过重载类实现的,系)编译时的多态性是通过重载类实现的,系统在编译时,根据传递的参数个数、类型信息统在编译时,根据传递的参数个数、类型信息决定实现何种操作。决定实现何种操作。(2 2)运行时的多态性是指在运行时,根据实际)运行时的多态性是指在运行时,根据实际情况决定实现何种操作。情况决定实现何种操作。C#C#中运行时的多态性中运行时的多态性通过虚函成员实现。通过虚函成员实现。4343版权所有版权所有C#程序设计与案例教程清华大学出版社如果希望基类中某个方法能够在派生类中进一步得如果希望基类中某个方法能够在派生类中进一步得到改进,那么可以把这个方法在基类中定义为虚到改进,
35、那么可以把这个方法在基类中定义为虚方法。类中的方法前加上了方法。类中的方法前加上了virtualvirtual修饰符成为虚方修饰符成为虚方法,反之为非虚方法。使用了法,反之为非虚方法。使用了virtualvirtual修饰符后不允修饰符后不允许再有许再有static,abstractstatic,abstract或或overrideoverride修饰符。修饰符。普通方法重载要求方法名称相同,参数类型和参数普通方法重载要求方法名称相同,参数类型和参数个数不同,而虚方法重载要求方法名称、返回值个数不同,而虚方法重载要求方法名称、返回值类型、参数表中的参数个数、类型顺序都必须与类型、参数表中的参数
36、个数、类型顺序都必须与基类中的虚函数完全一致。在派生类中声明对虚基类中的虚函数完全一致。在派生类中声明对虚方法的重载要求在声明中加上方法的重载要求在声明中加上overrideoverride关键字,而关键字,而不能有不能有newnew、staticstatic或或virtualvirtual修饰符。修饰符。4444版权所有版权所有C#程序设计与案例教程清华大学出版社2.5.3protected访问修饰符前面提到的protected访问修饰符可以将类成员的作用域限制在本类和由它所派生出的类中。例如在下面的代码中,将Weight成员变量声明为受保护后,就只有Animal和由它所派生的类可以访问该成
37、员变量了。4545版权所有版权所有C#程序设计与案例教程清华大学出版社【案例案例2-9】动物类。本案例用语演示保护成员的使用。4646版权所有版权所有C#程序设计与案例教程清华大学出版社2.5.4密封类C#提供一种不能被继承的类,称为密封类。密封类的声明方法是在类名前加上sealed修饰符。修饰符abstract和sealed不能同时使用。4747版权所有版权所有C#程序设计与案例教程清华大学出版社2.6抽象类与接口抽象类与接口2.6.12.6.1 抽象类抽象类当创建一个类时,有时需要让该类包含一些特殊当创建一个类时,有时需要让该类包含一些特殊的方法,该类对这些方法不提供具体实现,但该的方法,
38、该类对这些方法不提供具体实现,但该类的派生类必须实现这些方法,这些方法在类的派生类必须实现这些方法,这些方法在C#C#中中称为抽象方法。抽象方法必须是一个没有被实现称为抽象方法。抽象方法必须是一个没有被实现的空方法。包含抽象方法的类称为抽象类,抽象的空方法。包含抽象方法的类称为抽象类,抽象类中也可以包含非抽象方法。类中也可以包含非抽象方法。因为抽象类是用来作为基类的,所以不能直接被因为抽象类是用来作为基类的,所以不能直接被外部程序实例化,而且也不能被密封。外部程序实例化,而且也不能被密封。4848版权所有版权所有C#程序设计与案例教程清华大学出版社声明抽象方法的基本语法为:访问修饰符abstr
39、act返回类型方法名(参数列表);声明抽象类的基本语法为:访问修饰符abstract类名4949版权所有版权所有C#程序设计与案例教程清华大学出版社例如:publicabstractclassAnmialprotecteddoubleWeight;publicabstractvoidEat();/抽象方法5050版权所有版权所有C#程序设计与案例教程清华大学出版社当派生类从抽象类中继承一个抽象方法时,派生当派生类从抽象类中继承一个抽象方法时,派生类必须重载该抽象方法。下面代码中,类必须重载该抽象方法。下面代码中,CatCat类派生类派生自自AnimalAnimal类,并通过使用类,并通过使用o
40、verrideoverride关键字重载了关键字重载了AnimalAnimal类中的类中的EatEat方法。方法。publicclasspublicclassCat:AnimalCat:Animal publicoverridevoidEat()publicoverridevoidEat()Console.WriteLine(EatConsole.WriteLine(Eatfish);fish);5151版权所有版权所有C#程序设计与案例教程清华大学出版社【案例案例案例案例2-102-10】形状类。形状类。本案例定义一组具有继承关系的类。本案例定义一组具有继承关系的类。Shape(Shape(
41、形状形状)类是类是一个抽象类,包含了一个抽象类,包含了4 4个数据成员(坐标:个数据成员(坐标:x x、y,y,颜色颜色:c,:c,图形对象图形对象:g:g)、一个构造方法和两个抽象方法(求)、一个构造方法和两个抽象方法(求面积方法:面积方法:area()area(),画图的方法:,画图的方法:drawdraw()。()。Square(Square(正方形正方形)由由ShapeShape派生而来;派生而来;Rectangle(Rectangle(矩形矩形)由由SquareSquare派生而来;派生而来;Circle(Circle(圆圆)由由ShapeShape派生而来。派生而来。5252版权所
42、有版权所有C#程序设计与案例教程清华大学出版社2.6.2接口一个接口定义一个协定。实现接口的类或结构必须遵守其协定。在某种程度上,接口像一个抽象类。和任何类一样,接口可以定义方法、属性、事件等。但是,接口不提供成员的实现。实现接口的任何类都必须提供接口中所声明的抽象成员的定义。5353版权所有版权所有C#程序设计与案例教程清华大学出版社1接口声明接口声明接口声明的格式为:接口声明的格式为:访问修饰符访问修饰符 interfaceinterface 接口名接口名 :基接口:基接口 接口体接口体 5454版权所有版权所有C#程序设计与案例教程清华大学出版社接口体定义与类相似。要注意的是,接口的成员
43、可以是方法、属性、事件和索引,但不能是常数、字段、运算符、实例构造函数、析构函数或类型,也不能是任何种类的静态成员。此外,对接口还有以下限制:(1 1)接口可以用任何可访问性来声明,但接口)接口可以用任何可访问性来声明,但接口成员必须全都具有公共可访问性。成员必须全都具有公共可访问性。(2 2)不能向成员或接口自身附加安全性权限。)不能向成员或接口自身附加安全性权限。(3 3)接口可以定义类构造函数,但不能定义实)接口可以定义类构造函数,但不能定义实例构造函数。例构造函数。5555版权所有版权所有C#程序设计与案例教程清华大学出版社2 2接口实现接口实现接口实现接口实现接口可以由类和结构实现。
44、实现的接口的标识符出接口可以由类和结构实现。实现的接口的标识符出现在类的基列表中。现在类的基列表中。如下示例中,类如下示例中,类 EditBoxEditBox 从类从类 ControlControl派生,并且派生,并且同时实现同时实现IControlIControl和和IDataBoundIDataBound。interfaceinterfaceIDataBoundIDataBound voidvoidBind(BinderBind(Binderb);b);publicclasspublicclassEditBoxEditBox:Control,:Control,IControlIContro
45、l,IDataBoundIDataBound publicvoidPaint().publicvoidPaint().publicvoidpublicvoidBind(BinderBind(Binderb).b).5656版权所有版权所有C#程序设计与案例教程清华大学出版社【案例案例2-11】栈。本案例实现了一个字符栈。5757版权所有版权所有C#程序设计与案例教程清华大学出版社3 3接口的用处接口的用处接口的用处接口的用处 一个设计良好的接口可以包含一个紧密相关的功一个设计良好的接口可以包含一个紧密相关的功能集合,这些功能定义了一些特定的行为。当一能集合,这些功能定义了一些特定的行为。当一个
46、类实现了这个接口时,该类就实现了这些行为。个类实现了这个接口时,该类就实现了这些行为。可以为接口扩展新的增强实现,而不破坏现有的可以为接口扩展新的增强实现,而不破坏现有的代码,因此使用接口使得程序的兼容性增强,另代码,因此使用接口使得程序的兼容性增强,另外也可以通过开发新的接口或接口的新的实现来外也可以通过开发新的接口或接口的新的实现来增强功能。接口的用处具体体现在下面几个方面:增强功能。接口的用处具体体现在下面几个方面:(1 1)通过接口实现不相关类的相同行为,而无需)通过接口实现不相关类的相同行为,而无需考虑这些类之间的关系。考虑这些类之间的关系。(2 2)通过接口指明多个类需要实现的方法
47、。)通过接口指明多个类需要实现的方法。(3 3)通过接口了解对象的交互界面,而无需了解)通过接口了解对象的交互界面,而无需了解对象所对应的类。对象所对应的类。5858版权所有版权所有C#程序设计与案例教程清华大学出版社4 4接口与抽象类的比较接口与抽象类的比较接口与抽象类的比较接口与抽象类的比较 抽象类是一种不能实例化的类,通常是部分实现的抽象类是一种不能实例化的类,通常是部分实现的或完全不实现的,从而它可以用来封装类的通用或完全不实现的,从而它可以用来封装类的通用功能。功能。与抽象类不同的是,接口是一个完全抽象的成员集与抽象类不同的是,接口是一个完全抽象的成员集合。这个成员集合为相关操作定义
48、了一个规则。合。这个成员集合为相关操作定义了一个规则。接口的实现完全留给类设计者去完成。接口的实现完全留给类设计者去完成。使用抽象类的好处是:通过更新父类,所有派生类使用抽象类的好处是:通过更新父类,所有派生类都将自动进行相应更新。而接口在创建后就不能都将自动进行相应更新。而接口在创建后就不能再更改了。如果需要修改接口,则必须创建新的再更改了。如果需要修改接口,则必须创建新的接口。表接口。表2-52-5给出了选择接口和抽象类的一些建议。给出了选择接口和抽象类的一些建议。5959版权所有版权所有C#程序设计与案例教程清华大学出版社2.7委托与事件委托与事件2.7.1委托委托属于引用类型,其作用类
49、似于委托属于引用类型,其作用类似于 C+C+中函数中函数指针的用途。与函数指针不同,委托实例独立指针的用途。与函数指针不同,委托实例独立于它所封装的方法的类;最主要的是那些方法于它所封装的方法的类;最主要的是那些方法与委托的类型是兼容的。另外,函数指针只能与委托的类型是兼容的。另外,函数指针只能引用静态函数,而委托可以引用静态和实例方引用静态函数,而委托可以引用静态和实例方法。法。6060版权所有版权所有C#程序设计与案例教程清华大学出版社【案例案例2-12】演示委托。本案例演示委托的定义和使用方法。6161版权所有版权所有C#程序设计与案例教程清华大学出版社2.7.22.7.2事件事件事件是
50、对象发送的消息,以发信号通知操作的发生。事件是对象发送的消息,以发信号通知操作的发生。操作可能是由用户交互(例如鼠标单击)引起的,操作可能是由用户交互(例如鼠标单击)引起的,也可能是由某些其他的程序逻辑触发的。引发也可能是由某些其他的程序逻辑触发的。引发(触发)事件的对象叫做事件发送方。捕获事件(触发)事件的对象叫做事件发送方。捕获事件并对其作出响应的对象叫做事件接收方。并对其作出响应的对象叫做事件接收方。在事件通信中,事件发送方类不知道哪个对象或方在事件通信中,事件发送方类不知道哪个对象或方法将接收到(处理)它引发的事件。所需要的是法将接收到(处理)它引发的事件。所需要的是在源和接收方之间存