面向对象的高级编程_第1页
面向对象的高级编程_第2页
面向对象的高级编程_第3页
面向对象的高级编程_第4页
面向对象的高级编程_第5页
已阅读5页,还剩38页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、1 1第第5 5章章 面向对象的高级编程面向对象的高级编程5.1 5.1 类的继承与多态性类的继承与多态性5.5.2 2 接口接口 5.5.3 3 委托和事件委托和事件2 25.1 5.1 类的继承与多态性类的继承与多态性封装:隐藏调用者不需要了解的信息。封装:隐藏调用者不需要了解的信息。继承:简化类的设计。继承:简化类的设计。多态:类为名称相同的方法提供不同实现方式的能力。多态:类为名称相同的方法提供不同实现方式的能力。3 35.1.1 5.1.1 基类和扩充类基类和扩充类( (派生类)派生类) 继承表示现实世界中遗传关系的直接模继承表示现实世界中遗传关系的直接模拟。拟。 它表示类之间的内在

2、联系以及对属性和它表示类之间的内在联系以及对属性和操作的共享。操作的共享。4 45.1.1 5.1.1 基类和扩充类基类和扩充类声明扩充类的语法:声明扩充类的语法: 访问修饰符访问修饰符 class class 扩充类名称:基类名称扩充类名称:基类名称 / /程序代码,字段,属性,方法程序代码,字段,属性,方法 扩充类继承了所有定义在基类中数据的定义和方法。但扩充类继承了所有定义在基类中数据的定义和方法。但是是扩充类不继承基类的构造函数扩充类不继承基类的构造函数,不能继承基类中所定义,不能继承基类中所定义的的privateprivate成员,只能继承基类的成员,只能继承基类的publicpub

3、lic或或protectedprotected成员成员。两种实现继承的方式:类继承和接口继承。两种实现继承的方式:类继承和接口继承。类继承只允许单一继承类继承只允许单一继承 ,接口可实现多重继承。,接口可实现多重继承。被继承的类叫基类被继承的类叫基类继承自其他类的类叫扩充类继承自其他类的类叫扩充类(或者称为派生类)(或者称为派生类)5 5上午2时38分默认基类默认基类class class MyClassMyClass / /程序代码程序代码 不指定基类,则默认基类是不指定基类,则默认基类是System.ObjectSystem.Object实际上,即使声明某个类继承自另一个类,但是由于另一个

4、类仍然是从实际上,即使声明某个类继承自另一个类,但是由于另一个类仍然是从System.ObjectSystem.Object类一级一级地继承过来的,因此也可以说,任何一个类,类一级一级地继承过来的,因此也可以说,任何一个类,其最初都是从其最初都是从System.ObjectSystem.Object类继承来的,即它是所有类的祖先。类继承来的,即它是所有类的祖先。6 6【例例5-15-1】基类和扩充类的定义及用法基类和扩充类的定义及用法public class Animal public class Animal public int MyProperty get; set; public in

5、t MyProperty get; set; public Animal( public Animal( ) Console.WriteLine( Console.WriteLine(基类构造函数:基类构造函数:Hello, Animal!); Hello, Animal!); public void Eat( public void Eat( ) Console.WriteLine( Console.WriteLine(基类方法:基类方法:Eating); Eating); public class Cat : Animal public class Cat : Animal public

6、Cat( public Cat( ) ) Console.WriteLine( Console.WriteLine(扩充类构造函数:扩充类构造函数:Hello, Cat!);Hello, Cat!); public void Walk( public void Walk( ) ) Console.WriteLine(“ Console.WriteLine(“扩充扩充类方法类方法:Walk);Walk); 7 7上午2时38分【例例5-15-1】基类和扩充类的定义及用法基类和扩充类的定义及用法(续)(续)class Programclass Program static void Main(st

7、ring args) static void Main(string args) Cat cat = new Cat( Cat cat = new Cat( );); cat.Eat( cat.Eat( );); Console.ReadLine( Console.ReadLine( );); 类类CatCat继承自类继承自类AnimalAnimal,当创建当创建CatCat的实例时,的实例时,会首先调用基类的构造会首先调用基类的构造函数,然后调用扩充类函数,然后调用扩充类的构造函数。的构造函数。基类构造函数:基类构造函数:Hello, Animal!Hello, Animal!扩充类构造函数

8、:扩充类构造函数:Hello, Cat!Hello, Cat!基类方法:基类方法:EatingEating8 8上午2时38分多态性多态性是指对象可以表示多个类型的能力。是指对象可以表示多个类型的能力。在在C#C#中,多态性的定义是:同一操作作用于不同的类的实中,多态性的定义是:同一操作作用于不同的类的实例,不同的类将进行不同的解释,最后产生不同的执行结果。例,不同的类将进行不同的解释,最后产生不同的执行结果。简单地说,建立一个父类的对象,它的内容可以是这个父简单地说,建立一个父类的对象,它的内容可以是这个父类的,也可以是它的子类的,如果子类和父类都定义有同样的类的,也可以是它的子类的,如果子

9、类和父类都定义有同样的方法,多态性研究对象如何调用父类和子类的同名方法。方法,多态性研究对象如何调用父类和子类的同名方法。class A class A MethodAMethodA()() class B:A class B:A MethodAMethodA()() 5.1.2 5.1.2 多态性多态性多态技术是一种代码重用技术,表现为一种程序的组织结构。9 9多态性的实现方法多态性的实现方法3 3种实现多态性的方法:种实现多态性的方法: 通过继承实现多态性。通过继承实现多态性。n 多个类可以继承自同一个类,每个扩充类又可根据需要重写基类成多个类可以继承自同一个类,每个扩充类又可根据需要重写

10、基类成员以提供不同的功能。通过重写或隐藏基类的同名方法实现。员以提供不同的功能。通过重写或隐藏基类的同名方法实现。 通过抽象类实现多态性。通过抽象类实现多态性。n 抽象类本身不能被实例化,只能在扩充类中通过继承使用。抽象类抽象类本身不能被实例化,只能在扩充类中通过继承使用。抽象类的部分或全部成员不一定都要实现,但是要在继承类中全部实现。的部分或全部成员不一定都要实现,但是要在继承类中全部实现。抽象类中已经实现的成员仍可以被重写,并且继承类仍可以实现其抽象类中已经实现的成员仍可以被重写,并且继承类仍可以实现其他功能。他功能。 通过接口实现多态性。通过接口实现多态性。n 接口用于声明类需要实现的方

11、法、属性和事件,以及每个成员需要接口用于声明类需要实现的方法、属性和事件,以及每个成员需要接收和返回的参数类型,而这些成员的特定实现留给继承接口的类接收和返回的参数类型,而这些成员的特定实现留给继承接口的类去完成。去完成。10105.1.2 5.1.2 多态性多态性1 1、虚拟方法、虚拟方法 在基类中,如果想让某个方法或者事件被扩充类重写,可在基类中,如果想让某个方法或者事件被扩充类重写,可以使用修饰符以使用修饰符virtualvirtual表明:表明: public public virtualvirtual void void myMethodmyMethod( ) /( ) /虚方法虚方

12、法 /程序代码程序代码 扩充类则用扩充类则用overrideoverride重写重写: : public public overrideoverride void void myMethodmyMethod( ) /( ) /重写基类的虚方法重写基类的虚方法 /程序代码程序代码 11115.1.2 5.1.2 多态(续)多态(续)使用虚拟方法和重写方法时,要注意下面几个方面:使用虚拟方法和重写方法时,要注意下面几个方面:虚拟方法不能声明为静态虚拟方法不能声明为静态( (static)static)的。的。v virtualirtual不能和不能和privateprivate一起使用。一起使用。

13、重写方法的名称、参数个数、类型以及返回值都必须和重写方法的名称、参数个数、类型以及返回值都必须和虚拟方法的一致。虚拟方法的一致。1212【例例5-25-2】重写基类的方法。重写基类的方法。class Shapeclass Shape public virtual void ShowShape( public virtual void ShowShape( ) ) Console.WriteLine( Console.WriteLine(图形图形!); !); class Triangle : Shapeclass Triangle : Shape public override void Sh

14、owShape( public override void ShowShape( ) ) base.ShowShape(base.ShowShape( );); / /调用基类中的方法调用基类中的方法 Console.WriteLine( Console.WriteLine(三角形三角形!);!); class Program class Program static void Main( static void Main( ) ) Triangle me = new Triangle( Triangle me = new Triangle( );); me.ShowShape( me.Sho

15、wShape( );); 输出结果:图形!三角形!注:如果派生类没有定义ShowShape方法,me.ShowShape( )调用的是基类的方法。因为派生类继承了基类的方法。1313上午2时38分多态对象多态对象public class Dimensions public const double pi = Math.PI; protected double x, y; public Dimensions (double x, double y) this.x = x; this.y = y; public virtual double Area( ) return x*y; public c

16、lass Circle: Dimensions public Circle(double r): base(r, 0) public override double Area( ) return pi * x * x; public static void Main( ) double x = 3.0, y = 5.0; Dimensions a = new Dimensions(x,y); Dimensions c = new Circle(x); /多态对象 Console.WriteLine(Area of Dim = 0:F2, a.Area( ); Console.WriteLine

17、(Area of Circle = 0:F2, c.Area( );用基类类名声明但是用派生用基类类名声明但是用派生类构造函数创建的对象称为多类构造函数创建的对象称为多态对象。多态对象调用派生类态对象。多态对象调用派生类的重写方法。的重写方法。 1414上午2时38分多态对象多态对象public class Dimensions public const double pi = Math.PI; protected double x, y; public Dimensions (double x, double y) this.x = x; this.y = y; public virtual

18、 double Area( ) return x*y; public class Circle: Dimensions public Circle(double r): base(r, 0) public override double Area( ) return pi * x * x; public static void Main( ) double ComputArea(Dimensions D) Console.WriteLine(Area of Dim = , D.Area( ); double x = 3.0, y = 5.0; Dimensions a = new Dimens

19、ions(x,y); Dimensions c = new Circle(x); ComputArea(a); ComputArea(c);计算面积的方法在主程序中是统一的。1515上午2时38分多态技术的应用和流程共享多态技术的应用和流程共享 设有一个基类,名为设有一个基类,名为“公司公司”,它定义了做为公司的最基本,它定义了做为公司的最基本的数据成员类型和的数据成员类型和5050个最基本的虚方法。派生类有:个最基本的虚方法。派生类有:“制造业制造业公司公司”、“运输业公司运输业公司”、“餐饮旅游业公司餐饮旅游业公司”、“贸易业公贸易业公司司”。每个派生类都在基类的基础上作了扩展,并且按照行

20、业。每个派生类都在基类的基础上作了扩展,并且按照行业的特点重写了虚方法。每个派生类都产生了许多对象,一个对的特点重写了虚方法。每个派生类都产生了许多对象,一个对象代表一家公司。象代表一家公司。税务局检查税收,调用每家公税务局检查税收,调用每家公司的下列方法:司的下列方法:统计所有职工();统计所有职工();统计营业总额();统计营业总额();税收记录();税收记录();计算应缴税款();计算应缴税款();社保局检查四金,调用每家公社保局检查四金,调用每家公司的下列方法:司的下列方法:统计职工人数();统计职工人数();统计工商事故();统计工商事故();统计医药费();统计医药费();检查三金

21、支付和适用();检查三金支付和适用();检查税收(制造业对象)、检查税收(运输业对象),检查税收(制造业对象)、检查税收(运输业对象),。编。编写每个公司的这些流程,代码重复,繁琐。写每个公司的这些流程,代码重复,繁琐。1616上午2时38分多态技术的应用和流程共享(续) 基类中使用虚方法;基类中使用虚方法; 派生类中按需要重写方法;派生类中按需要重写方法; 设计流程,完成某个特殊的任务,例如设计流程,完成某个特殊的任务,例如public void public void 检查税收检查税收( (基类名基类名 DObjDObj) ) DObjDObj. .统计所有职工统计所有职工( )( );

22、DObjDObj. .统计营业总额统计营业总额( );( ); 创建多态对象,例如创建多态对象,例如CompanyXCompanyX; 基类名基类名 CompanyXCompanyX = = new new 制造业制造业( );( ); 将多态对象作为实参,调用流程:将多态对象作为实参,调用流程: 检查税收检查税收( (CompanyXCompanyX) ) 按照这样的程序结按照这样的程序结构,不同的任务可构,不同的任务可以建立不同的流程,以建立不同的流程,以后任务改变了,以后任务改变了,只要改变流程即可,只要改变流程即可,每个参与的对象都每个参与的对象都共享同一个流程,共享同一个流程,流程共

23、享也是一种流程共享也是一种代码重用技术。代码重用技术。多态技术:将同一基类的各个派生类组织起来。以基类对象为参数的方多态技术:将同一基类的各个派生类组织起来。以基类对象为参数的方法形成流程,以各个派生类重写的基类虚方法完成具体的任务。法形成流程,以各个派生类重写的基类虚方法完成具体的任务。1717上午2时38分多态技术的应用举例 public class Test public static void Evaluate(Student stu) stu.Commonweal( ); stu.PhyEdu( ); stu.GradePoint( ); / 流程设计 public static v

24、oid Main( ); /每个数组元素为多态对象 Student Stus=new Student2; Student0=new CompuStu(); foreach(Student stud in Stus) Evaluate(stud); public class Student / 基类 / 评估体育水平 public virtual void PhyEdu( ) / 评估德语水平 public virtual void Commonweal( ) / 评估智育水平 public virtual void GradePoint( ) public class CompuStu:Stu

25、dent / 评估体育水平 public override void PhyEdu( ) / 评估德语水平 public override void Commonweal( ) / 评估智育水平 public override void GradePoint( ) 18185.1.2 5.1.2 多态(续)多态(续)2 2、隐藏基类的方法、隐藏基类的方法 在扩充类中,可以使用在扩充类中,可以使用newnew关键字来隐藏基类的方法,即关键字来隐藏基类的方法,即使用一个完全不同的方法取代旧的方法。使用一个完全不同的方法取代旧的方法。 与方法重写不同的是,使用与方法重写不同的是,使用newnew关键

26、字时并不要求基类中关键字时并不要求基类中的方法声明为的方法声明为virtualvirtual,只要在扩充类的方法前声明为,只要在扩充类的方法前声明为newnew,就可以隐藏基类的方法。就可以隐藏基类的方法。 使用场合举例:要求开发人员重新设计基类中的方法,使用场合举例:要求开发人员重新设计基类中的方法,该基类是一年前由另一组开发人员设计的,并且已经交给用该基类是一年前由另一组开发人员设计的,并且已经交给用户使用,可是原来的开发人员在该方法前并没有加户使用,可是原来的开发人员在该方法前并没有加virtualvirtual关键字,但又不允许修改原来的程序。这种情况下显然不能关键字,但又不允许修改原

27、来的程序。这种情况下显然不能使用使用overrideoverride重写基类中的方法,这时就需要隐藏基类的方重写基类中的方法,这时就需要隐藏基类的方法。法。1919public class Hello public class Hello public void SayHello( public void SayHello( ) Console.WriteLine() Console.WriteLine(这是基类的方法这是基类的方法); ); public class NewHello : Hellopublic class NewHello : Hello public new void S

28、ayHello( public new void SayHello( ) Console.WriteLine() Console.WriteLine(这是扩充类的新方这是扩充类的新方法法);); class Program class Program static void Main( static void Main( ) ) Hello Hello a a = new Hello( = new Hello( );); a a.SayHello(.SayHello( );); NewHello NewHello b b = new NewHello( = new NewHello( ););

29、 b b.SayHello(.SayHello( );); Hello c = new NewHello(Hello c = new NewHello( ); /); /多态对象多态对象 c.SayHello(c.SayHello( );); 【例例5-35-3】隐藏基类的方法隐藏基类的方法即使派生类中隐藏了基类中的同名方法,多态对象调用基类中的方法。2020上午2时38分5.1.2 5.1.2 多态(续)多态(续)3.3.在扩充类直接调用基类的方法在扩充类直接调用基类的方法 使用使用basebase关键字关键字class Shapeclass Shape public virtual voi

30、d ShowShape( public virtual void ShowShape( ) ) Console.WriteLine( Console.WriteLine(图形图形!); !); class Triangle : Shapeclass Triangle : Shape public override void ShowShape( public override void ShowShape( ) ) base.ShowShape(base.ShowShape( );); / /调用基类中的方法调用基类中的方法 Console.WriteLine( Console.WriteLi

31、ne(三角形三角形!);!); 21215.1.3 5.1.3 抽象类抽象类抽象类抽象类使用使用abstractabstract修饰符修饰符,用于表示类中的成员不一定,用于表示类中的成员不一定全部实现,即可以只有声明部分而没有实现部分。全部实现,即可以只有声明部分而没有实现部分。抽象类只能做基类。抽象类只能做基类。抽象类与非抽象类的区别:抽象类与非抽象类的区别: 第一是抽象类不能直接被实例化,只能在扩充类中通过继第一是抽象类不能直接被实例化,只能在扩充类中通过继承使用,对抽象类使用承使用,对抽象类使用newnew运算符生成对象会产生编译时错误。运算符生成对象会产生编译时错误。 第二个不同点是抽

32、象类可以包含抽象成员第二个不同点是抽象类可以包含抽象成员(有(有abstractabstract修修饰符的成员)饰符的成员),而非抽象类不能包含抽象成员。当从抽象类派,而非抽象类不能包含抽象成员。当从抽象类派生非抽象类时,非抽象类必须具体实现所继承的所有抽象成员。生非抽象类时,非抽象类必须具体实现所继承的所有抽象成员。抽象类应用场合:如果有一个通用方法,该方法对所有派生类抽象类应用场合:如果有一个通用方法,该方法对所有派生类来说是公共的,并且强制要求所有派生类必须实现这个方法,来说是公共的,并且强制要求所有派生类必须实现这个方法,可以将该方法定义为基类中的抽象方法。可以将该方法定义为基类中的抽

33、象方法。2222上午2时38分抽象类抽象类和抽象方法举例和抽象方法举例public abstract class Shape public abstract class Shape / / 抽象类抽象类 public virtual void Draw( public virtual void Draw( ) ) Console.WriteLine( Console.WriteLine(画一种图形画一种图形!); !); public abstract void Rotate( public abstract void Rotate( ); ); / / 抽象成员抽象成员, ,没有实现部分没有

34、实现部分 public class Square : Shapepublic class Square : Shape public override void Draw( public override void Draw( ) Console.WriteLine() Console.WriteLine(画一个正方形画一个正方形! !);); public override void Rotate( public override void Rotate( ) Console.WriteLine(“) Console.WriteLine(“顺时针方向旋顺时针方向旋转正方形转正方形!”);!”

35、); /抽象方法的实现抽象方法的实现 class Program class Program static void Main(string args) static void Main(string args) Square me = new Square( Square me = new Square( );); me.Draw( me.Draw( ); me.Rotate(); me.Rotate( );); 23235.1.4 5.1.4 密封类密封类 密封类是指不能被其他类继承的类。密封类是指不能被其他类继承的类。 在在C#C#语言中,使用语言中,使用sealedsealed关键字声

36、明密封类。关键字声明密封类。 sealedsealed关键字也可以限制基类中的方法,防止被扩充类重写,关键字也可以限制基类中的方法,防止被扩充类重写,带有带有sealedsealed修饰符的方法称为密封方法。密封方法同样不能被修饰符的方法称为密封方法。密封方法同样不能被扩充类中的方法继承,也不能被隐藏。扩充类中的方法继承,也不能被隐藏。 使用密封方法的场合举例:如果某个方法重写了基类中同名的使用密封方法的场合举例:如果某个方法重写了基类中同名的方法,但是又不希望该方法所在类的扩充类重写该方法,就可方法,但是又不希望该方法所在类的扩充类重写该方法,就可以在该方法前使用修饰符以在该方法前使用修饰符

37、sealedsealed。24245.1.5 5.1.5 继承过程中构造函数的处理继承过程中构造函数的处理 C#C#在内部按照下列顺序处理构造函数:从扩充类依次向上寻在内部按照下列顺序处理构造函数:从扩充类依次向上寻找其基类,直到找到最初的基类,然后开始执行最初的基类找其基类,直到找到最初的基类,然后开始执行最初的基类的构造函数,再依次向下执行扩充类的构造函数,直至执行的构造函数,再依次向下执行扩充类的构造函数,直至执行完最终的扩充类的构造函数为止。完最终的扩充类的构造函数为止。注意:注意: 对于无参数的构造函数,对于无参数的构造函数,按照上面的顺序按照上面的顺序执行执行,不会出现问不会出现问

38、题。题。 如果无参数的构造函数如果无参数的构造函数和和带参数的构造函数带参数的构造函数同时存在同时存在,建议建议使用下例所示的方法使用下例所示的方法显式调用基类的构造函数显式调用基类的构造函数。2525【例例5-55-5】继承机制中构造函数的用法继承机制中构造函数的用法class A class A protected int age; protected int age; public A( ) Console.WriteLine(A:0,age); public A( ) Console.WriteLine(A:0,age); public A(int age) this.age = ag

39、e;Console.WriteLine(A:0, public A(int age) this.age = age;Console.WriteLine(A:0, age);age); class B : A class B : A public B( ) : base( ) public B( ) : base( ) Console.WriteLine(B:0, age); Console.WriteLine(B:0, age); public B(int age) : base(age) public B(int age) : base(age) age = 5;age = 5; Conso

40、le.WriteLine(B:0, age); Console.WriteLine(B:0, age); class Program class Program static void Main( static void Main( ) ) B b1 = new B( B b1 = new B( );); / /A A:0 B0 B:0 0 B b2 = new B(10);B b2 = new B(10);/A A:10 B10 B:5 5 26265.5.2 2 接口接口 接口的主要特点是只有声明部分,没有实现部分。接口的主要特点是只有声明部分,没有实现部分。 接口成员的实现是通过类完成的

41、。接口成员的实现是通过类完成的。 定义在接口中的方法都是定义在接口中的方法都是publicpublic的的,不能再用,不能再用publicpublic修饰修饰符声明符声明。 使用使用interfaceinterface关键字声明一个接口。常用的语法是:关键字声明一个接口。常用的语法是: 访问修饰符访问修饰符 interface interface 接口名称接口名称 / / 接口体接口体 一般情况下,以大写的一般情况下,以大写的“I I”开头指定接口名,表明这是开头指定接口名,表明这是一个接口。一个接口。 需要在不相关的类中实现同样的功能时,可以使用接口。需要在不相关的类中实现同样的功能时,可以

42、使用接口。2727上午2时38分接口接口的用途的用途 接口表示调用者和设计者的一种约定。例如,提供的某个接口表示调用者和设计者的一种约定。例如,提供的某个方法用什么名字、需要哪些参数,以及每个参数的类型是方法用什么名字、需要哪些参数,以及每个参数的类型是什么等。什么等。 在多人合作开发同一项目时,事先定义好相互调用的接口在多人合作开发同一项目时,事先定义好相互调用的接口可以大大提高项目开发效率。可以大大提高项目开发效率。 当其他设计者调用了声明的接口后,就不能再随意更改接当其他设计者调用了声明的接口后,就不能再随意更改接口的定义,否则项目开发人员之间事先的约定就失去意义。口的定义,否则项目开发

43、人员之间事先的约定就失去意义。 C#C#中,一个类可以继承多个接口。中,一个类可以继承多个接口。2828【例例5-75-7】接口的声明与实现接口的声明与实现interface Ifunction1 int sum(int x1, int x2); interface Ifunction1 int sum(int x1, int x2); interface Ifunction2 string MyString get; set; interface Ifunction2 string MyString get; set; class MyTest : Ifunction1, Ifunction

44、2 class MyTest : Ifunction1, Ifunction2 private string myString; private string myString; public MyTest( public MyTest( ) ) public MyTest(string str) myString = str; public MyTest(string str) myString = str; / /实现接口实现接口Ifunction1Ifunction1中的方法中的方法 public int sum(int x1, int x2) return x1 + x2; publi

45、c int sum(int x1, int x2) return x1 + x2; / /实现接口实现接口Ifunction2Ifunction2中的属性中的属性 public string MyString public string MyString get return myString; get return myString; set myString = value; set myString = value; 2929上午2时38分【例例5-75-7】接口的声明与实现接口的声明与实现(续)(续)class Programclass Program static void Main

46、(string args) static void Main(string args) Ifunction1 f1 = new MyTest( Ifunction1 f1 = new MyTest( );); / /接口对象接口对象 Console.WriteLine(f1.sum(20, 30); Console.WriteLine(f1.sum(20, 30); Ifunction2 f2 = new MyTest(“How are you”); Ifunction2 f2 = new MyTest(“How are you”); / /接口对象接口对象 Console.WriteLine

47、(f2.MyString); Console.WriteLine(f2.MyString); MyTest C1 = new MyTest(MyTest C1 = new MyTest( );); / /类对象类对象 Console.WriteLine(C1.sum(20, 30); Console.WriteLine(C1.sum(20, 30); MyTest C2 = new MyTest(“How are you”); MyTest C2 = new MyTest(“How are you”); / /类对象类对象 Console.WriteLine(C2.MyString); Con

48、sole.WriteLine(C2.MyString); 可以通过接口对象和类对象访问方法,二者结果一致。3030显式方式实现接口显式方式实现接口由于不同接口中的方法可以重名,因此,在一个类中实现由于不同接口中的方法可以重名,因此,在一个类中实现接口中的方法时就存在着多义性的问题。通过显式方式实现接接口中的方法时就存在着多义性的问题。通过显式方式实现接口解决此类问题。口解决此类问题。注意:注意:显式实现接口时,不能通过类的实例进行访问,而显式实现接口时,不能通过类的实例进行访问,而必须使用接口实例。必须使用接口实例。3131上午2时38分【例例5-85-8】以显式方式实现接口以显式方式实现接口

49、interface Ifunction int sum(int x1, int x2); interface Ifunction int sum(int x1, int x2); class MyTest : Ifunction class MyTest : Ifunction / /显显式式实现接口实现接口IfunctionIfunction中的方法中的方法 int Ifunction.sum(int x1, int x2) return x1 + x2; int Ifunction.sum(int x1, int x2) return x1 + x2; class Program clas

50、s Program static void Main( static void Main( ) ) MyTest myTest = new MyTest( MyTest myTest = new MyTest( );); / /类对象类对象 Ifunction b = new MyTest( Ifunction b = new MyTest( );); / /接口对象接口对象 Console.WriteLine(b.sum(20, 30); Console.WriteLine(b.sum(20, 30); Console.WriteLine(myTest.sum(20, 30); / Cons

51、ole.WriteLine(myTest.sum(20, 30); /错误错误, ,不能通过类的实不能通过类的实例访问接口方法例访问接口方法 Console.ReadLine();Console.ReadLine(); 32325.5.3 3 委托和事件委托和事件1.1.委托委托(delegatedelegate) 类似与类似与C+C+中的函数指针,不同的是中的函数指针,不同的是C+C+语言的函数指针只能够语言的函数指针只能够指向静态的方法,而委托除了可以指向静态的方法之外,还可指向静态的方法,而委托除了可以指向静态的方法之外,还可以指向对象实例的方法。以指向对象实例的方法。 可以利用委托在程

52、序执行时传入方法的名称,动态地决定欲调可以利用委托在程序执行时传入方法的名称,动态地决定欲调用的方法。用的方法。 委托的最大特点是:它不知道或不关心自己引用的对象的类。委托的最大特点是:它不知道或不关心自己引用的对象的类。 使用委托使程序员可以将方法引用封装在委托对象内。然后可使用委托使程序员可以将方法引用封装在委托对象内。然后可以将该委托对象传递给可调用所引用方法的代码以将该委托对象传递给可调用所引用方法的代码 。 任何对象中的方法都可以通过委托动态地调用,只是方法的任何对象中的方法都可以通过委托动态地调用,只是方法的参参数类型和返回类型数类型和返回类型必须与委托的参数类型和返回类型相匹配。

53、必须与委托的参数类型和返回类型相匹配。 委托的应用:回调(委托的应用:回调(CallBackCallBack)机制、事件处理。)机制、事件处理。3333上午2时38分委托的声明和使用委托的声明和使用委托的声明和使用委托的声明和使用访问修饰符访问修饰符 delegate delegate 返回类型返回类型 委托名(参数序列)委托名(参数序列) 例如例如:publicpublic delegatedelegate void void FuncDelegateFuncDelegate(stringstring strstr);); 定义了一个名为定义了一个名为FuncDelegateFuncDele

54、gate的委托,它包含了一个的委托,它包含了一个stringstring类类型的传入参数型的传入参数strstr,返回类型为,返回类型为voidvoid。 当当C#C#编译器编译这行代码时,会为其生成一个新的类,该类继编译器编译这行代码时,会为其生成一个新的类,该类继承自承自System.DelegateSystem.Delegate类,而类的名称为类,而类的名称为FuncDelegateFuncDelegate。 定义委托类似于定义一个方法,但是没有方法体,因为它执行定义委托类似于定义一个方法,但是没有方法体,因为它执行的方法在使用委托时动态指定的。的方法在使用委托时动态指定的。3434【例

55、例5-95-9】委托的用法委托的用法 /第一步:声明委托第一步:声明委托public delegate string MyDelegate(string name);public delegate string MyDelegate(string name);public class Program public class Program / /第二步:定义被调用的方法第二步:定义被调用的方法 /必须与委托一致必须与委托一致: : 参数类型、参数个数、参数顺序、返回类型参数类型、参数个数、参数顺序、返回类型 public static string FunctionA(string name

56、)public static string FunctionA(string name) return A say Hello to + name; return A say Hello to + name; public static string FunctionB(string name) public static string FunctionB(string name) return B say Hello to + name; return B say Hello to + name; / /第三步:定义第三步:定义delegatedelegate类型的处理函数,类型的处理函数,

57、相当于事件处理函数,一般相当于事件处理函数,一般在最后由程序员编写,但是,委托机制是事先设计好了在最后由程序员编写,但是,委托机制是事先设计好了。 /通过通过delegatedelegate类型调用类型调用步骤步骤二二定义的方法定义的方法 public static void MethodA(MyDelegate Me) public static void MethodA(MyDelegate Me) Console.WriteLine(Me( Console.WriteLine(Me(张三张三); ); 3535上午2时38分【例例5-95-9】委托的用法委托的用法(续)(续) publi

58、c static void Main(public static void Main( ) ) / /第四步:第四步:创建创建委托委托实例实例,传入准备调用的方法名传入准备调用的方法名 MyDelegate a = new MyDelegate(FunctionA);MyDelegate a = new MyDelegate(FunctionA); / /委托对象委托对象 MyDelegate b = new MyDelegate(FunctionB); MyDelegate b = new MyDelegate(FunctionB); / /委托对象委托对象 MethodA(a); Meth

59、odA(a); MethodA(b); MethodA(b); Console.ReadLine( Console.ReadLine( );); A say Hello toA say Hello to 张三张三B B say Hello to say Hello to 张三张三委托对象封装方法时并不关心该方法属于什么类,只要该方法的参数列表和委托对象封装方法时并不关心该方法属于什么类,只要该方法的参数列表和返回类型满足条件即可。返回类型满足条件即可。委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递

60、,这种将方法动态地赋给参数的做法,可以避免在程序中大量数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用使用If-If-Else(SwitchElse(Switch) )语句,同时使得程序具有更好的可扩展性。语句,同时使得程序具有更好的可扩展性。 36365.5.3 3 委托和事件委托和事件2.2.事件事件 事件是用户某个操作引发的要求程序响应的请求,发出请求只事件是用户某个操作引发的要求程序响应的请求,发出请求只是要求得到响应和处理,并不知道谁来处理,发出请求者称为是要求得到响应和处理,并不知道谁来处理,发出请求者称为事件发送方,而接收事件并处理事件的程序称为事件的接收方

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论