C#面向对象编程深入.ppt

上传人:牧羊曲112 文档编号:6502434 上传时间:2023-11-07 格式:PPT 页数:49 大小:710KB
返回 下载 相关 举报
C#面向对象编程深入.ppt_第1页
第1页 / 共49页
C#面向对象编程深入.ppt_第2页
第2页 / 共49页
C#面向对象编程深入.ppt_第3页
第3页 / 共49页
C#面向对象编程深入.ppt_第4页
第4页 / 共49页
C#面向对象编程深入.ppt_第5页
第5页 / 共49页
点击查看更多>>
资源描述

《C#面向对象编程深入.ppt》由会员分享,可在线阅读,更多相关《C#面向对象编程深入.ppt(49页珍藏版)》请在三一办公上搜索。

1、第8章 C#面向对象编程深入,本章要点,8.1 接口 8.2 委托8.3 事件8.4 匿名方法,8.1 接口,8.1.1 定义接口8.1.2 接口的实现,8.1 接口概述,定义接口的语法如下:interface:在关键字之前,包含一个访问修饰符,后面紧跟着接口标识符。:可选部分,用于指定接口继承的父接口列表,接口允许多继承,所以从理论上讲,一个接口可继承无数个接口。习惯上,接口标识符以大写字母I开头。因为,接口可以强制类实现抽象成员,所以接口标识符通常以_able结尾。,8.1.1 定义接口,接口成员 接口继承列表后面是接口的主体。主体由包围在大括号中的成员组成。合法的成员如下:方法属性索引事

2、件,8.1.1 定义接口,注意:所有的接口成员,都不能包含访问修饰符。所有成员都隐式地声明为public,因为它们要从实现接口成员所在的类的外部访问。在接口中定义的属性和索引可以有一个抽象的get访问器,或者一个抽象的set访问器,或者二者兼有。接口事件与普通事件的声明方式一样。,8.1.1 定义接口,接口与类 接口的定义很像类或结构,它定义了类必须实现的行为类型的特征,相当于一份使用者和实现者之间的合同。接口可以看做只包含抽象函数的纯抽象类。接口最终还是需要由类(或者结构)来实现,也就要求类要实现接口的抽象函数成员,这与派生类保证要实现它的基类的抽象函数一样。所以接口是通过动态捆绑函数调用纯

3、抽象的基类的替代方式。,8.1.1 定义接口,即使接口和抽象类在句法和语义上紧密相关,但它们仍有一个重要的区别:接口只能包含抽象函数、抽象的属性和抽象的索引,而抽象类还可能包含数据成员,以及完全实现的函数、属性和索引。也正是如此,多重接口才不会像多重继承那样存在出现问题的可能性。如此一来,得到一个结论:一个类最多可以具有一个基类,但可以具有无限个接口。,8.1.2 实现接口,接口自身并不包含任何实现代码,落实这种定义了的“合同”的任务最终落到了类(或结构)身上。在C#中,实现接口的方式有两种:隐式实现显式实现例子:ExplicitInterface.sln,8.1.2 实现接口,显式实现的主要

4、用途是在有多个接口继承,并且两个或多个接口使用了同一个名称声明成员的场合。要执行显式实现,类中需要使用它的完全限定名来实现接口成员,而且在调用时,必须将类的对象实例转换成单独的接口类型。也就是说,要把类对象引用强制转换为接口类型来获取接口的引用。一旦有了接口的引用,我们就可使用点号来调用接口的方法。对于隐式实现而言,它和直接由基类产生派生类的方式很相似。例子:InterfaceExample.sln,8.2 委托,8.2.1 引例8.2.2 定义委托8.2.3 实例化委托8.2.4 通过委托调用方法8.2.5 多重委托,8.2 委托概述,编写源代码时,如果我们只知道特定的位置必定发生某动作,并

5、不知道它的具体实现过程,就可以用委托。C#的委托是一个类型安全方法引用,可以把引用存储为函数的类型。通过委托,程序能够在运行时刻动态地调用不同的方法。委托最重要的作用是建立支持事件的基础结构。,8.2.1 引例,例子:在一个拥有多种降温设备(例如:电力空调、干冰降温机、气动降温机等)的生物实验室里,因为要完成某项试验,要求室内温度低于某个临界温度值。可以想见,如果实验室内温度显著升高或者达到某个较高值,就必须启用某些降温设备,来控制室内温度的升高。为此,就要求控制用的软件系统必须在适当的时候启用适当的降温设备。,8.2.1 引例,为此,设计的控制软件可以尝试采用下面这两种方式来实现:软件驱动各

6、个降温设备经常地测量室内温度,根据温度变化,各个降温设备自动启用。使用一个监视室内温度的模块,当温度变化时,就启动合适的降温设备。,8.2.1 引例,这两种方式都有其弱点。在第一种方式中,如果测量的频率太频繁,将耗费资源,影响软件性能,但如果测量次数太少,又可能会漏掉某些突然变化的情况,导致错过降温时机,所以不宜采用;第二种方式面临的问题就是:对于不同的降温设备,要使用不同的控制方法,对于编程而言,会导致过于复杂,并难以维护。,8.2.1 引例,要解决这个问题,推荐使用委托。委托与抽象方法一样,它指定了方法的返回类型和形式参数类型,但没有指定具体的实现过程,只要这些方法与委托的签名(返回类型及

7、形式参数)相同。同一个委托在运行期间可以表示不同的方法实现过程。只是在运行时,为委托赋一个适当的方法,当调用此委托时,它将执行此方法实际所封装的代码。,8.2.2 定义委托,委托定义了方法的返回类型和参数类型,也创建了一种新类型,每个使用委托的方法都必须提供。委托也是一个类,它派生于基类System.Delegate。和其他类一样,必须首先定义委托,然后才能实例化。下面给出了委托定义的语法:modifiers delegate(parameter list);其中modifiers(访问修饰符)和parameter(参数)是可选项。下面是声明委托的例子:public delegate doub

8、le Calculation(double val1,double val2),8.2.3 实例化委托,定义了委托之后,必须要实例化委托,还需要委托的方法处理程序,这个方法实现具体的功能,其参数列表必须相同,并且必须返回同样的类型。然后再将这个方法赋给委托对象。,8.2.3 实例化委托,public delegate double Calculation(double var1,double var2);public class Example/实例化委托.Calculation CalcInstance;public double MyMethod(double var1,double va

9、r2)./接通委托和方法.CalcInstance=new Calculation(MyMethod);,8.2.4 通过委托调用方法,通过上述工作,我们就可以使用委托了。使用委托就好像它就是委托的方法本身一样,和直接使用方法的格式相同。我们可以通过下面的语句,来调用委托:double result=CalcInstance(2455.589d,448247.45d);上面的语句和下面的语句等价:double result=MyMethod(2455.589d,448247.45d);,补充:声明委托类型,委托是类型,就好像类是类型一样。与类一样,委托类型必须在被用来创建变量以及类型的对象之前

10、声明。delegate void MyDel(int x);委托类型的声明看上去与方法的声明很相似,有返回类型和签名。返回类型和签名指定了委托接受的方法的形式。,补充:创建委托对象,委托是引用类型,因此有引用和对象。在委托类型声明之后,我们可以声明变量并创建类型的对象。有两种创建委托对象的方式:第一种是使用带new运算符的对象创建表达式,new运算符的操作数组成下:委托类型名;一组圆括号,其中包含作为调用列表中第一个成员的方法的名字。方法可以是实例方法,也可以是静态方法。delVar=new MyDel(myInsObj.MyM1);/创建委托并保存引用(实例方法)dVar=new MyDel

11、(SClass.OtherM2);/创建委托并保存引用(静态方法),补充:创建委托对象,第二种是快捷语法。delVar=myInsObj.MyM1;/创建委托并保存引用(实例方法)dVar=SClass.OtherM2;/创建委托并保存引用(静态方法)例子:Delegates.sln,补充:创建委托对象,8.2.5 多重委托,多重委托(multicast delegate)是由两个或更多的其他委托构成的委托。它可以封装一个或多个方法。当调用多重委托时,会逐个调用封装的所有方法(这对于事件处理特别有用)。,8.2.5 多重委托,在C#中,通过使用加法(+)运算符,可以把某个委托添加到一个多重委托

12、中。类似地,通过使用删除(-)运算符,可以把某个委托从多重委托中删除。也可以把多个委托添加到一个多重委托中。当多重委托被调用时,已经添加的每个委托就按其被添加的顺序调用。,补充:多重委托,MyDel delA=myInstObj.MyM1;MyDel delB=SClass.OtherM2;MyDel delC=delA+delB;第三个委托是由前两个委托组成。例子:Delegates.sln,补充:多重委托,补充:调用带返回值的委托,如果委托有返回值,并且在调用列表中有一个以上的方法,会发生下面的情况:调用列表中最后一个方法返回的值就是委托调用返回的值;调用列表中所有其它方法的返回值都会被忽

13、略。例子:Delegates.sln,补充:调用带引用参数的委托,如果委托有引用参数,参数值会根据调用列表中的一个或者多个方法的返回值而改变。在调用委托列表中的下一个方法时,参数的新值(不是初始值)会传给下一个方法。例子:Delegates.sln,8.3 事件,8.3.1 定义事件8.3.2 订阅事件8.3.3 实现事件8.3.4 触发事件,8.3.1 定义事件,在C#中,事件实际上是委托的一种特殊形式。事件是为处理过程特制的更为专业化的委托。下面是定义事件的格式:modifiers event type name;其中modifiers(修饰符)和方法定义中的一样,可以使用new、publ

14、ic、protect、private、static、virtual、sealed、override、abstract。紧接着要使用关键字event。在名称之前,还必须确定事件的类型,因为所有的事件是一类特殊的委托,它们都是基于委托的,所以type必须是委托类型。,8.3.2 订阅事件,事件发生了,如何将它和事件处理的程序联系起来呢?这就要用到订阅器,它是订阅事件的对象。我们先看看在闹铃模拟程序中是如何编辑的,代码如下:clock.Alarm+=new AlarmEventHandler(waking.AlarmRing);其中,clock是AlarmClock类的一个实例,通过“+=”操作符将

15、事件与新创建的委托联系起来。委托的方法是waking.AlarmRing,这是一个事件处理方法,在后面会讲到。,8.3.2 订阅事件,订阅事件也很简单,通过加运算符(+=)就能完成事件的附加。依此类推,我们可以使用删除事件运算符(-=),将在事件中分离订阅器,分离可以防止从发行器对象发送来任何后续事件的通知。注意:普通的委托和事件间的主要区别之一是:在附加和分离事件时,只能使用”+=”和”-=”这两种运算符。,8.3.3 实现事件,接收到事件通知后,如何处理?在委托中确定了相关的处理方法,该方法必须符合事件委托类型的签名(返回类型和参数类型)。,8.3.3 实现事件,在本例中处理事件的方法如下

16、:public class WakeMeUp public void AlarmRang(object sender,AlarmEventArgs e)在WakeMeUp类中,定义了一个无返回值的方法AlarmRang,其参数是object sender和AlarmEventArgs e。,8.3.4 触发事件,我们要明确:事件不是将各个程序片段串起来的管道,所以,程序也就不能沿着这个管道顺流而下。通过这种方式使程序更具有交互性、灵活性和动态性。本例中触发事件的语句是:Alarm(this,e);其形式上和方法的调用非常类似。例子:Events.sln,补充:事件的5个源代码组件,补充:使用E

17、ventArgs类,EventArgs is the base class for classes containing event data.This class contains no event data;it is used by events that do not pass state information to an event handler when an event is raised.If the event handler requires state information,the application must derive a class from this

18、class to hold the data.,补充:使用EventArgs类,EventArgs被设计为不能传递任何数据。如果希望传递数据,必须声明一个从EventArgs继承的类,使用合适的字段来保存需要传递的信息。尽管EventArgs类实际上并不能传递数据,但它是使用EventHandler委托模式的重要一部分。不管参数使用的实际类型是什么,object类和EventArgs总是基类。这样EventHandler就能提供一个对所有事件和事件处理器都通用的名字,只允许2个参数,而不是各自有各自的签名。,补充:通过扩展EventArgs类来传递数据,为了向自己的事件处理程序的第二个参数传入

19、数据,并且又符合标准惯例,我们需要声明一个派生自EventArgs类的自定义类,它可以保存我们所需传入的数据。类的声明应该以EventArgs结尾。例子:EventArgsClassExample.sln,8.4 匿名方法,8.4.1 匿名方法的定义8.4.2 委托作为参数和返回值,匿名方法(Anonymous Method)就是没有名称的方法,使用它可以跳过方法的定义,而将方法的执行代码直接封装到一个委托对象中。除了可以简化代码外,匿名方法的重要用途还包括共享对本地语句包含的函数成员的访问,在多个方法间进行状态共享,以及将代码段作为参数传递。,8.4.1 匿名方法的定义,匿名方法允许定义一个

20、由委托调用的匿名方法,它直接将一个委托关联的代码内联写入到使用委托的地方。匿名方法表达式由3部分组成:关键字delegate、参数列表以及执行代码段,其中只有参数列表部分可以省略。其一般形式为:delegate(参数列表)/执行代码段,8.4.1 匿名方法的定义,要注意的是:匿名方法表达式本身并不是一个完整的语句,只有将它赋值给一个委托对象才能构成一个语句。在赋值给某个委托对象时,要求匿名方法表达式与委托的定义保持一致,其要求如下:匿名方法表达式可以省略参数列表,而其对应的委托类型可以包含任意个参数,但不能包含输出参数,而且不能再代码执行段中使用这些参数。,8.4.1 匿名方法的定义,如果匿名

21、方法表达式指定了参数列表,则参数数量和参数类型必须与委托中定义的相同,或者参数类型可以隐式的转换到委托中对应的参数类型。匿名方法表达式的参数列表中不能包含特性和参数数组(关键字params修饰的数组)。,8.4.1 匿名方法的定义,匿名方法表达式的返回类型(指的是其执行代码段中return语句的返回类型)必须和委托定义的返回类型相同,或者可以隐式的转换为委托的返回类型。如果存在多个return语句,则要求每个语句的返回类型相同,并与委托定义的返回类型一致。如果委托定义的返回类型是void,那么执行代码段或者没有return语句,或者是不带任何表达式的、单独的return语句。例子:AnonymousMethod.sln,8.4.2 委托作为参数和返回值,由于委托本身是一种数据类型,所以委托对象可以作为变量使用。但委托的特殊性在于它封装了方法,于是它既具有变量的说明性,又具有方法的过程性。如果将委托对象作为参数传递给其他方法,或者由方法返回一个委托对象,这就实现了以往程序设计语言,特别是过程化程序设计语言很难实现的一个功能:将过程(子程序)作为参数和返回值进行传递,这种方式却带来了巨大的高效性和灵活性。,Thank You!,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号