第四面向对象编程进阶.ppt

上传人:本田雅阁 文档编号:3136445 上传时间:2019-07-15 格式:PPT 页数:67 大小:1.61MB
返回 下载 相关 举报
第四面向对象编程进阶.ppt_第1页
第1页 / 共67页
第四面向对象编程进阶.ppt_第2页
第2页 / 共67页
第四面向对象编程进阶.ppt_第3页
第3页 / 共67页
第四面向对象编程进阶.ppt_第4页
第4页 / 共67页
第四面向对象编程进阶.ppt_第5页
第5页 / 共67页
点击查看更多>>
资源描述

《第四面向对象编程进阶.ppt》由会员分享,可在线阅读,更多相关《第四面向对象编程进阶.ppt(67页珍藏版)》请在三一文库上搜索。

1、第四章 面向对象编程进阶,本章学习目标,理解类的继承与多态的概念 熟悉类型转换的方法 掌握结构与接口的定义及用法 掌握异常处理的方法 掌握委托的定义及用法,第四章 面向对象编程进阶,4.1 类的继承与多态 4.3 类型转换 4.4 结构与接口 4.6 异常处理 4.7 委托,4.1 类的继承与多态,4.1.1 继承 4.1.2 多态,4.1.1 继承,类的继承性:C#允许基于某一个已经定义的类来创建一个新类。 基类:被继承的类,即父类。 派生类:继承的类,即子类。,4.1.1 继承,访问修饰符 class 类名 : 基类 类主体 访问修饰符: public:表示不限制对类的访问; intern

2、al:可被同一个项目的程序访问; sealed: 表示一个密封类,不能被继承。 说明:如果对类不指定访问修饰符,则类的默认访问修饰符为internal,定义派生类,4.1.1 继承,class Person public string name; protect string sex; int age; class Student : Person string stuNo; string classNo; ,定义派生类,4.1.1 继承,派生类只能继承于一个基类; 派生类自然继承基类的成员,但不能继承基类的构造函数成员; 类的继承可以传递。如C类继承B类,B类继承A类,则C类具有B类和A类的

3、成员; 派生类是对基类的扩展,派生类定义中可以声明新的成员; 派生类定义中如果声明了与基类同名的成员,则基类的同名成员将被隐藏,从而使派生类不能直接访问同名的基类的成员; 基类可以定义虚方法成员等,这样派生类能够覆盖这些成员以表现类的多态性。,类的继承规则,4.1.1 继承,派生类构造函数,默认执行基类的无参构造函数,如果要执行基类有参构造函数,则必须在派生类构造函数的基表列表中指出; 构造函数调用顺序:先基类后派生类。,派生类析构函数,析构函数调用顺序:先派生类后基类。,4.1.1 继承base,在派生类中调用基类方法 在构造函数中显式调用基类构造函数 public 派生类名(形参列表):

4、base(基类构造函数实参列表) 在方法中调用基类方法 base.基类方法名(参数表),4.1.1 继承隐藏,隐藏 自动隐藏与基类同名的成员 声明成员时,显式使用new修饰符,隐藏实质上是使继承的成员在派生类成为不可见的。隐藏的成员并没有被删除,只是不能从派生类直接访问,通过基类能够直接访问它。,4.1.2 多态,编译时实现的多态: 如果一个类中有两个或两个以上的方法的名字相同,而它们的形参个数或形参类型有所不同,在程序编译时能够正确区别他们; 运行时实现的多态: 指在程序运行时,基类对象执行一个基类与派生类都具有的同名方法调用时,程序可以根据基类对象类型的不同(基类还是派生类)进行正确的调用

5、。 实现方法:虚方法、抽象方法,4.1.2 多态虚方法,public virtual 返回类型 方法名(参数列表) 方法体 ,基类中定义虚方法,public override 返回类型 方法名(参数列表) 方法体 ,派生类中重写基类中定义虚方法,4.1.2 多态虚方法,几点说明: 基类与派生类中的方法名、参数列表、返回类型必须完全一致; 可被重写的基类方法是虚方法、抽象方法或重写方法(override修饰) virtual不能与static、abstract或override中任一个同时出现; override不能与new、static、virtual或abstract中任一个同时使用;,4.

6、1.2 隐藏与多态实例,隐藏与多态,class A public void E() Console.WriteLine(“A.E”); public void F() Console.WriteLine(“A.F”); public virtual void G() Console.WriteLine(“A.G”); class B:A public void E() Console.WriteLine(“B.E”); public new void F() Console.WriteLine(“B.F”); public override void G() Console.WriteLine

7、(“B.G”); class Test public static void Main() B b=new B(); A a=b; a.E(); b.E(); a.F(); b.F(); a.G(); b.G(); ,输出结果: A.E B.E A.F B.F B.G B.G,父类可以引用子类对象,父类引用只能调用子类继承自父类的方法,父类不能调用子类独有的方法。,4.1.2 隐藏与多态实例,隐藏与多态,class A public virtual void F() Console.WriteLine(“A.F”); class B:A public override void F() Con

8、sole.WriteLine(“B.F”); class C :B new public virtual void F() Console.WriteLine(“C.F”); class D :C public override void F() Console.WriteLine(“D.F”); class Test public static void Main() D d=new D(); A a=d; B b=d; C c=d; a.F(); b.F(); c.F(); d.F(); ,输出结果: B.F B.F D.F D.F,4.1.2 多态抽象类与抽象方法,抽象类:是一种特殊的基

9、类,该类并不与具体的事物发生联系;例如几何体,计算几何体体积的方法不可能有具体实现过程,只有具体某一种几何体才有求体积的方法; 抽象类是指在基类的定义中声明不包含任何实现代码的方法,实际上就是一个不具有任何具体功能的方法,即抽象方法。该方法的唯一作用就是让派生类来重写; 在基类定义中,只要类体中包含一个抽象方法,该类即为抽象类。,4.1.2 多态抽象类与抽象方法,public abstract class 类名 public abstract 返回类型 方法名称(参数列表); ,声明抽象类与抽象方法,不包含方法体, 也不能要,4.1.2 多态抽象类与抽象方法,抽象类几点说明 一个类中只要包含一

10、个抽象方法,该类即为抽象类;反之,一个抽象类中必须包含抽象方法; 抽象类中可以包含非抽象方法; 抽象类不能实例化,不能用new生成实例; 抽象类不能被密封。 派生类说明 如果基类为抽象类,则要求派生类必须重载实现基类中所有抽象方法。 抽象方法说明 抽象方法没有方法体,只有一个方法头后跟一个分号; 抽象方法被隐含认为是一种虚方法,派生类中必须重写所有抽象方法,且重写的方法与抽象方法的参数及类型、方法名都应相同。,4.1.2 多态抽象类与抽象方法,public abstract class Shape protected double x; protected double y; protecte

11、d double z; public Shape(double dx, double dy, double dz) x=dx; y=dy; z=dz; public abstract double Cubage(); ,定义抽象类及抽象方法,4.1.2 多态抽象类与抽象方法,public class Cuboid:Shape public Cuboid(double dx, double dy, double dz) :base(dx,dy,dz) public override double Cubage() return x * y * z; ,重载抽象方法,4.1.2 多态抽象类与抽象方

12、法,虚方法与抽象方法区别 抽象方法必须在抽象类中定义,虚方法可以在抽象类或一般类中定义; 在基类中,虚方法用virtual关键字,抽象方法用abstract关键字; 在派生类中,虚方法不一定重写,抽象方法一定要重写;,修饰符小结,基类方法,abstract,virtual,override,无说明符,new (无说明符),override,派生类方法,4.1.2 多态密封类和密封方法,密封类:不允许被继承的类。,定义密封类,访问修饰符 sealed class 类名称 类体 ,public sealed class SealedClass public string method( ) ret

13、urn “我是密封类“; ,定义密封类,4.1.2 多态密封类和密封方法,基类中要密封的方法必须有virtual、abstract或override 派生类中的密封方法必须同时有sealed override。,定义密封方法,访问修饰符 sealed override 返回类型 方法名(参数列表) 方法体 ,4.1.2 多态密封类和密封方法,密封方法,class A public virtual void F() Console.WriteLine(“A.F”); class B:A public sealed override void F() Console.WriteLine(“B.F”

14、); class C :B public override void F() Console.WriteLine(“C.F”); class Test public static void Main() C c=new C(); c.F(); ,sealed必须与override同时出现,不允许重写F方法 若无override则为隐藏,4.3 类型转换,4.3.1 隐式类型转换 4.3.2 显式类型转换 4.3.3 使用Convert转换,为什么需要类型转换,编译器要确切地知道数据的类型,int num = “123“ ;,整数,字符串,需要类型转换!,编译出错,4.3.1 隐式类型转换,隐式

15、转换:自动类型转换,float,int,规则:对于数值类型,A的取值范围完全包含在B内,A,B,static void Main(string args) double score = 58.5; / 原始成绩 int bonus = 2; / 加分 int sum; / 总分 sum = score + bonus; / 计算总分 Console.WriteLine(sum); Console.ReadLine(); ,4.3.2 显式类型转换,static void Main(string args) double score = 58.5; int bonus = 2; int sum;

16、 sum = (int)score + bonus; Console.WriteLine(sum); Console.ReadLine(); ,明确告诉编译器转换类型 注意:double (58.5)-int (58),精度可能丢失!,显式转换:强制类型转换,使用 Parse() 进行转换,字符串和数值型的互相转换,int,float,double,string,int.Parse( ),float.Parse( ),double.Parse( ),ToString(),必须是数字的 有效表示形式!,4.3.3 使用 Convert 类进行转换,使用 Convert :Convert.ToXx

17、x(object value),Convert.ToInt32(),Convert.ToSingle(),Convert.ToString(),double 85.63,string “85.63“,int 86,float 85.63,Parse 与 Convert,Xxx.Parse(string),目标类型的有效表示形式,Convert.ToXxx(object):,注:Xxx表示某种类型,字符串,其他类型,任意类型,其他类型,4.4 结构与接口,访问修饰符struct 结构名 结构主体 访问修饰符: public:表示不限制对结构的访问; internal: 可被同一个项目的程序访问(

18、默认); 结构成员包括字段、属性、方法等; 结构可以定义构造函数,但不能定义析构函数; 有一个默认的不带参数的构造函数, 用于对结构的字段进行初始化,并且结构的默认构造函数不能被重写。,结构的声明,4.4 结构与接口,结构与类的区别,4.4 结构与接口,struct account public string name; public double balance; public account(string n,double b) name=n;balance=b; ,结构定义及使用(一),4.4 结构与接口,结构定义及使用(一)续,class Test public static void

19、 Main() account acc1=new account(“张三”,3000); /显式构造函数 account acc2=new account(); /缺省构造函数 account acc3; /没有构造函数 Console.WriteLine(acc1.name+“has a balance of ”+acc1.balance); if(acc2.name=null) Console.WriteLine(“acc2.name is null”); Console.WriteLine(“acc2.balance is ”+acc2.balance); /使用acc3以前,必须初始化

20、acc3 acc3.name=“Mary”; acc3.balance=2000; Console.WriteLine(acc3.name+“has a balance of ”+acc3.balance); ,4.4 结构与接口,struct MyStruct public int x; public int y; public MyStruct(int i, int j) x = i; y = j; public void Sum() int sum=x+y; Console.WriteLine(“The sum is 0”,sum); ,结构定义及使用(二),4.4 结构与接口,clas

21、s Test static void Main() MyStruct s1 = new MyStruct(1,2); MyStruct s2 = s1; s1.x = 2; s1.Sum(); s2.Sum(); ,结构定义及使用(二)续,输出结果: The sum is 4 The sum is 3,值传递,4.4 结构与接口,接口声明定义了一个协定,使用接口的类或结构必须遵守其协定。接口可以从多个基接口继承,而类或结构可以实现多个接口; 接口成员只能是方法、属性、索引和事件,不能有字段。 接口本身不提供它所定义成员的实现代码,只指定实现该接口的类或结构必须提供的成员的调用形式。,4.4 结

22、构与接口,访问修饰符 interface 接口名 :基接口1,基接口2 接口体 访问修饰符: public:表示不限制对类的访问; internal: 可被同一个项目的程序访问(默认); 接口成员包括属性、方法等; 接口不能包括字段,也不能定义构造函数和析构函数; 接口成员访问修饰符默认为public; 接口的命名通常是以I开头,如IPartA。,接口的声明,4.4 结构与接口,接口的实现 函数成员的实现:类、结构; 实现接口类型: public成员实现 显示接口成员实现 不能用new操作符创建接口的实例,4.4 结构与接口,public成员实现 实现接口成员时,声明成员为public,这样的

23、实现声明称为public接口成员实现声明,简称public成员实现或public实现; public实现的成员具有双重访问性,因为它是接口成员的实现,所以可以通过接口实例来访问,又因为它是public成员,还可以通过类或结构的实例来访问。,4.4 结构与接口,interface IA void p(); class B:IA public void p() /代码实现 class Test public static void Main() B b=new B(); b.p(); IA a=b; a.p(); ,public成员实现(一),(正确),(正确),4.4 结构与接口,public成

24、员实现(二),interface IPoint int Xget;set; int Yget;set; class MyPoint:IPoint private int myX,myY; public MyPoint(int x,int y) myX=x;myY=y; public int X /对属性X的public实现声明 getreturn myX; setmyX=value; public int Y /对属性Y的public实现声明 getreturn myY; setmyY=value; ,4.4 结构与接口,class MainClass /通过接口调用 public stati

25、c void PrintPoint(IPoint p) Console.WriteLine(“x=0,y=1”,p.X,p.Y); public static void Main() MyPoint p=new MyPoint(2,3); Console.Write(“MyPoint:”); PrintPoint(p); ,public成员实现(二)续,输出结果: MyPoint:x=2,y=3,4.4 结构与接口,显式接口成员实现 用接口成员的完全限定名(接口名.成员名)来显式指定要实现的接口成员,这样的实现声明称为显式接口成员实现声明,简称显式实现声明; 注意:显式实现声明中不能用publ

26、ic修饰符。,4.4 结构与接口,interface IA void p(); class B:IA void IA.p() /代码实现 class Test public static void Main() B b=new B(); b.p(); IA a=b; a.p(); ,显式成员实现(一),(错误),(正确),4.4 结构与接口,interface IA void p(); interface IB void p(); class C:IA,IB void IA.p()Console.WriteLine(“A.p”); void IB.p()Console.WriteLine(“B

27、.p”); public void p() Console.WriteLine(“C.p”); class Test public static void Main() C c=new C(); c.p(); (IA)c).p(); (IB)c).p(); ,显式成员实现(二),输出结果: C.p A.p B.p,4.4 结构与接口,interface IA void p(); class B:IA void IA.p()Console.WriteLine(“A.p”); public void p() Console.WriteLine(“B.p”); class C:B,IA public

28、 static void Main() B b=new B(); IA a=b; a.p(); /显式接口成员实现优先 C c=new C(); a=c; c.p(); a.p(); ,显式成员实现(三),输出结果: A.p B.p A.p,类可以同时有一个基类和零个以上的接口,并将基类写在前面,4.6 异常处理,异常 指由于程序运行时发生的错误,从而导致程序错误结束。 异常处理 当程序运行过程中发生了某个异常现象,系统将产生一个相应的异常类对象,并把它交给系统处理,系统负责找到处理错误的代码并执行, 如除数为0。,4.6 异常处理,使用语句或表达式在执行过程中自动引发了某个异常的条件,使得操

29、作无法正常结束,从而引发异常; 使用显式 throw 语句来引发异常。在此情况下,控制权将无条件转到处理异常的部分代码。,引发异常两种方式,C#中异常处理语句,trycatch trycatchfinally tryfinally throw,4.6 异常处理,try 被监控的可能发生异常的程序代码 catch(异常类名 异常变量名) 异常处理 ,格式1,try 被监控的可能发生异常的程序代码 finally 最终要执行的代码 ,格式2,try 被监控的可能发生异常的程序代码 catch(异常类名 异常变量名) 异常处理 finally 最终要执行的代码 ,格式3,4.6 异常处理,try子句

30、包含可能引起异常的代码; 只有发生异常时才执行catch子句,若没有异常,try子句正常结束,catch子句被忽略,程序转到catch后的第一条语句开始执行; 可以包含多个catch语句; catch子句可以不包括参数,它将捕获所有类型的异常; 异常类名必须为System.Exception或从System.Exception派生的类型; finally子句不管有没有异常都执行。,4.6 异常处理,4.6 异常处理,int num1, num2,result; try num1 = int.Parse(Console.ReadLine(); num2 = int.Parse(Console.R

31、eadLine(); result = num1 / num2; Console.WriteLine(“商是”+result); catch(DivideByZeroException error) Console.WriteLine(“除数不能为零!“); catch (FormatException error) Console.WriteLine(“输入格式错误!“); catch(Exception ex) /如果写,写在catch的最后 Console.WriteLine(“输入错误”); finally Console.WriteLine(“谢谢使用!“);,异常处理,4.6 异常

32、处理,throw异常处理,static int Divide(int x,int y) try int z=x/y; return z; catch(DivideByZeroException error) throw new DivideByZeroException(“除数不能为0”); ,static void Main() int num1, num2,result; try num1 = int.Parse(Console.ReadLine(); num2 = int.Parse(Console.ReadLine(); result = Divide(num1,num2); Cons

33、ole.WriteLine(“商是”+result); catch(DivideByZeroException error) Console.WriteLine(error.Message); catch (FormatException error) Console.WriteLine(“输入格式错误!“); catch(Exception ex) Console.WriteLine(“输入错误”); finally Console.WriteLine(“谢谢使用!“); ,4.7 委托,委托也叫代理,就是把事情交给别人去办,如委托律师代理打官司,委托同学代买火车票; C#中如果将一个方法委

34、托给一个代理对象,那么这个对象就可以全权代理这个方法的执行; 使用委托首先要定义委托,声明委托能代理什么类型的方法,就像房产中介能代理抵押贷款业务,而不能代理打官司; 委托是一种类型,即它与class , interface , struct ,enum处于同一级别,而且它是引用类型; 任何委托类型都是system.delegate类的派生类。,4.7 委托,何时使用委托? (1)回调函数; (2)多线程编程中使用委托来指定启动一个线程时调用的方法; (3)C#中的事件模型。用它们指明处理给定事件的方法。,4.7 委托,委托用法步骤: (1)定义委托 访问修饰符 delegate 代理方法的返

35、回值类型 委托类型名(代理方法参数列表) (2)声明委托变量 委托类型名 委托对象; (3)实例化委托变量 委托对象=new 委托类型(对象名.方法名)/调用某类的实例方法 委托对象=new 委托类型(类名.方法名)/调用某类的静态方法 (4)调用委托,实现方法 委托对象(实参),实例化时必须指定方法名,4.7 委托,Void Multiply(int,int) . Void Divide(int,int) . ,可以引用任何方法,将在运行时决定,委托和方法必须具有相同的签名,- public delegate void Call(int num1, int num2); -,4.7 委托,定

36、义委托,namespace Delegates public delegate int Call(int num1, int num2); class Math public int Multiply(int num1, int num2) return num1*num2; public int Divide(int num1, int num2) return num1/num2; class TestDelegates public static void Main() Call objCall; Math math = new Math(); objCall = new Call(ma

37、th.Multiply); Console.WriteLine(“乘积是:”+objCall(1,2); ,将方法与委托关联起来,4.7 委托,回调函数,namespace Delegates public delegate int Call(int num1, int num2); class Math public int Multiply(int num1, int num2) return num1*num2; public int Divide(int num1, int num2) return num1/num2; class TestDelegates public stati

38、c void Main() Call objCall1,objCall2; Math math = new Math(); objCall1 = new Call(math.Multiply); objCall2 =new Call(math.Divide); int mul = Process(2,2,objCall1); int div = Process(2,2,objCall2); Console.WriteLine(“乘积是:”+mul); Console.WriteLine(“商是:”+div); public static int Process(int num1,int num

39、2,Call calculate) return calculate(num1,num2); ,4.7 委托,delegate声明中的“返回值类型”要与方法返回类型一致; delegate声明中的“参数列表”要与方法的形参形表一致; 在委托的“实例化”的时候必须传入一个方法名。这个方法名就是该代理指向的方法。,委托要点:,4.7 委托多播,相对于一次委托只调用一个方法,一次委托也可以调用多个方法,称为多播; 通过+=和-=运算符(或+、-)实现多播的增加或减少; 如果调用多播委托,就可以按顺序连续调用多个方法。为此,委托的返回值类型就必须返回 void (否则,返回值应送到何处?)。,4.7

40、委托多播,多播委托,namespace Delegates public delegate int Call(int num1, int num2); class Math public int Multiply(int num1, int num2) Console.WriteLine( “乘积是”+num1*num2); public int Divide(int num1, int num2) Console.WriteLine( “商是”+num1/num2); class TestDelegates static void Main() Call objCall; Math math = new Math(); objCall = new Call(math.Multiply); objCall+= math.Divide; objCall(2,2); ,将方法添加到委托列表,总结,C#中类的继承与多态? C#中接口的定义及使用? C#中如何处理异常? C#中的委托?,

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

当前位置:首页 > 其他


经营许可证编号:宁ICP备18001539号-1