《c#课件第4章 面向对象的高级编程.ppt》由会员分享,可在线阅读,更多相关《c#课件第4章 面向对象的高级编程.ppt(53页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、11第第4 4章章 面向对象的高级编程面向对象的高级编程封装、封装、继承与多承与多态 版本控制版本控制接口接口 委托委托泛型泛型处理理 22本章教学目的本章教学目的介介绍面向面向对象高象高级编程的相关知程的相关知识,使学生,使学生对C#高高级编程有程有一个感性一个感性认识。本章教学要求本章教学要求(1)掌握)掌握继承、泛型的概念及基本用法;承、泛型的概念及基本用法;(2)掌握与)掌握与实验有关的相关内容,包括封装、有关的相关内容,包括封装、继承与多承与多态、泛型泛型处理理;(3)了解其他内容。)了解其他内容。33实验中的问题解答实验中的问题解答1.1.如何添加某个事件(例如窗体的如何添加某个事
2、件(例如窗体的Shown事件)?如何事件)?如何删除某个事件?除某个事件?答:添加和答:添加和删除事件均在除事件均在设计视图下利用属性中的事件完成。下利用属性中的事件完成。2.2.使用使用textBoxStartAmount.Focus();与使用与使用键让某控件某控件获取焦点有何不同?取焦点有何不同?答:前者用于答:前者用于动态设置,后者用于静置,后者用于静态设置。置。3.3.实验2:private double Caculate(double startAmount,double rate,int count)叠加次数叠加次数count是什么意思?是什么意思?答:叠加次数是指到期后将答:叠
3、加次数是指到期后将计算出来的利息作算出来的利息作为存款再次存款再次计算,例如存款算,例如存款时间为1年,年,则按年算息叠加次数按年算息叠加次数为1,按月算息叠加次数,按月算息叠加次数为12,按季度,按季度算息叠加次数算息叠加次数为4。4.4.实验报告什么告什么时候交?候交?进度如何安排?度如何安排?答:各人根据自己的情况安排答:各人根据自己的情况安排进度,完成一个,写一个度,完成一个,写一个实验报告。告。5.5.如何定如何定义属性?如何属性?如何给属性属性赋值?如何?如何获取属性的取属性的值?答:答:见书上上P59例例3-10444.1 4.1 封装、继承与多态封装、继承与多态封装:封装:隐藏
4、藏调用者不需要了解的信息。用者不需要了解的信息。继承:承:简化化类的的设计。多多态:类为名称相同的方法提供不同名称相同的方法提供不同实现方式的能力。方式的能力。55封装封装模模块信息通信息通过类封装封装类的成的成员通通过字段、属性、方法、事件封装字段、属性、方法、事件封装u私有的用私有的用privateu可以被可以被继承的用承的用protectedu公共成公共成员用用publicu不要不要为了方便把什么都定了方便把什么都定义成成publicu不要不要为了方便把什么都定了方便把什么都定义成成static通通过属性属性进行封装的例子:行封装的例子:P73例例4-166封装举例:封装举例:对象封装了
5、对象的数据以及对这些数据的操作。对象是属性和操作的组合对象的表现(服务、接口)和实现细节分开77/MyClass.csusing System;namespace ConsoleTest class MyClass private int number;public int Number get return number;set if(value 0)number=value;/Program.cs/Program.csusing System;using System;namespace ConsoleTestnamespace ConsoleTest public class Progr
6、am public class Program public static void Main()public static void Main()MyClass me=new MyClass me=new MyClass();MyClass();me.Number=-1;me.Number=-1;Console.WriteLine(Console.WriteLine(Number:0,Number:0,me.Number);me.Number);Console.ReadLine();Console.ReadLine();回答:回答:NumberNumber输出的值是多少?输出的值是多少?88
7、练习练习(1)(1)Question 47.(单选)In Object oriented Programming,how would you describe encapsulation?1.The conversion of one type of object to another.2.The runtime resolution of method calls.3.The exposition of data.4.The separation of interface and implementation.答案:答案:499继承继承继承表示承表示现实世界中世界中遗传关系的直接模关系的直接
8、模拟。它表示它表示类之之间的内在的内在联系以及系以及对属性和属性和操作的共享。操作的共享。1010继承(续)继承(续)声明声明扩充充类的的语法:法:访问修修饰符符 class 扩充充类名称:基名称:基类名称名称 /程序代程序代码 扩充充类继承了所有定承了所有定义在基在基类中数据的定中数据的定义和方法。但是和方法。但是扩充充类不不继承基承基类的构造函数的构造函数。继承的例子(承的例子(1):):P76例例4-2两种实现继承的方式:类继承和接口继承。两种实现继承的方式:类继承和接口继承。类继承只允许单一继承类继承只允许单一继承 ,接口可实现多重继承。,接口可实现多重继承。被继承的类叫基类被继承的类
9、叫基类继承自其他类的类叫扩充类继承自其他类的类叫扩充类1111多态多态用相同的操作名在一个用相同的操作名在一个类层次的不同次的不同类中中实现不同不同的功能,相同的消息由同一的功能,相同的消息由同一(父父)类的不同的不同对象接收象接收时,导致不同的行致不同的行为。举例:几何图形类层次中的多态性。其派生类“圆”、“长方形”、“三角形”等都有方法“求面积”。几何图形圆三角形几何图形圆ShapeShape类 GetArea()RectangleRectangle类GetArea()CircleCircle类GetArea()TriangleTriangle类GetArea()12121、虚、虚拟方法方
10、法 在基在基类中,如果想中,如果想让某个方法或者事件被某个方法或者事件被扩充充类重写,可以使用修重写,可以使用修饰符符virtual表明:表明:public virtual void myMethod()/程序代程序代码 扩充充类则用用override重写重写:public override void myMethod()/程序代程序代码多态(续)多态(续)1313/MyClass.csusing System;namespace ConsoleTest class MyClass public virtual void Hello()Console.WriteLine(123);/MyNew
11、Class.cs/MyNewClass.csusing System;using System;namespace ConsoleTestnamespace ConsoleTest class MyNewClass:MyClass class MyNewClass:MyClass private string str=private string str=hello;hello;public override void Hello()public override void Hello()Number=2;Number=2;Console.WriteLine(str);Console.Writ
12、eLine(str);1414多态(续)多态(续)使用虚使用虚拟方法和重写方法方法和重写方法时,要注意下面几个方面:,要注意下面几个方面:虚虚拟方法不能声明方法不能声明为静静态的。的。Virtual不能和不能和private一起使用。一起使用。重写方法的名称、参数个数、重写方法的名称、参数个数、类型以及返回型以及返回值都必都必须和和虚虚拟方法的一致。方法的一致。举例例 P79页例例4-41515多态(续)多态(续)2、隐藏基藏基类的方法的方法在在扩充充类中,可以使用中,可以使用new关关键字来字来隐藏基藏基类的方法,的方法,即使用一个完全不同的方法取代旧的方法。即使用一个完全不同的方法取代旧的
13、方法。与方法重写不同的是,使用与方法重写不同的是,使用new关关键字字时并不要求基并不要求基类中的方法声明中的方法声明为virtual,只要在,只要在扩充充类的方法前声明的方法前声明为new,就可以,就可以隐藏基藏基类的方法。的方法。1616多态(续)多态(续)3、抽象、抽象类使用使用abstract修修饰符。符。抽象抽象类只能做基只能做基类。抽象抽象类与非抽象与非抽象类的区的区别:第一是抽象第一是抽象类不能直接被不能直接被实例化,只能在例化,只能在扩充充类中通中通过继承使用,承使用,对抽象抽象类使用使用new运算符会运算符会产生生编译时错误第二个不同点是抽象第二个不同点是抽象类可以包含抽象成
14、可以包含抽象成员,而非抽象,而非抽象类不能包含抽象成不能包含抽象成员。当从抽象。当从抽象类派生非抽象派生非抽象类时,这些非抽象些非抽象类必必须具体具体实现所所继承的所有抽象成承的所有抽象成员。1717补充题目补充题目Question 32.(单选)以下描述以下描述错误的是()的是()1.在在C+中支持抽象中支持抽象类而在而在C#中不支持抽象中不支持抽象类。2.C+中可在中可在头文件中声明文件中声明类的成的成员而在而在CPP文件中定文件中定义类的成的成员,在,在C#中没有中没有头文件并且在同一文件并且在同一处声明和定声明和定义类的的成成员。3.在在C#中可使用中可使用 new 修修饰符符显式式隐
15、藏从基藏从基类继承的成承的成员。4.在在C#中要在派生中要在派生类中重新定中重新定义基基类的虚函数必的虚函数必须在前面在前面加加Override。1818练习(练习(2 2)abstract class BaseClass public virtual void MethodA()Console.WriteLine(BaseClass);class Class1:BaseClass public void MethodA()Console.WriteLine(Class1);class Class2:Class1 在在Main方法中方法中执行下列行下列语句:句:Class2 o=new Cla
16、ss2();o.MethodA();问:执行行结果是什么?果是什么?19194.2 4.2 版本控制版本控制 用用C#编写方法写方法时,如果在,如果在扩充充类中重写基中重写基类的方法,需要的方法,需要用用override声明;要声明;要隐藏基藏基类的方法,需要用的方法,需要用new声明,声明,这就是就是C#进行版本控制的依据。行版本控制的依据。调用非虚用非虚拟方法方法时不会受到版本的影响不会受到版本的影响调用虚用虚拟方法的方法的实现部分可能会因部分可能会因扩充充类的重写而影响的重写而影响执行行结果。果。举例:例:P83 例例4-8 P84 例例4-9 20204.2 4.2 版本控制(续)版本
17、控制(续)调用原用原则:调用用继承的最后承的最后实现部分的方法部分的方法 P85 例例4-10C#允允许派生派生类包含与基包含与基类方法名称相同的方法,方法名称相同的方法,规则如下:如下:1)基基类方法必方法必须声明声明为virtual2)若派生若派生类中方法前无中方法前无new或或override关关键字,方法字,方法执行按存行按存在在new关关键字一字一样执行行3)若派生若派生类中方法前中方法前带new关关键字,字,则此方法被定此方法被定义为独立于独立于基基类的方法的方法4)若派生若派生类中方法前中方法前带override关关键字,字,则派生派生类调用此方法用此方法,而非基,而非基类的方法
18、。的方法。5)可从派生可从派生类中使用中使用base关关键字字调用基用基类方法。方法。2121补充知识:补充知识:C#C#面试题面试题public class A public A()Console.WriteLine(“A”);public virtual void Fun()Console.WriteLine(A.Fun();public class B:A public class B:A public B()public B()Console.WriteLine(Console.WriteLine(“B B”););public new void Fun()public new voi
19、d Fun()Console.WriteLine(B.Fun();Console.WriteLine(B.Fun();public static void Main()public static void Main()A a=new B();A a=new B();a.Fun();a.Fun();/输出结果为:输出结果为:A A B B A.Fun A.Fun()()22224.3 4.3 接口接口 接口的主要特点是只有声明部分,没有接口的主要特点是只有声明部分,没有实现部分。部分。接口成接口成员的的实现是通是通过类完成的。完成的。定定义在接口中的方法都是在接口中的方法都是public的。的。
20、使用使用interface关关键字声明一个接口。常用的字声明一个接口。常用的语法是:法是:访问修修饰符符 interface 接口名称接口名称 /接口体接口体 一般情况下,以大写的一般情况下,以大写的“I”开开头指定接口名,表明指定接口名,表明这是一是一个接口。个接口。需要在不相关的需要在不相关的类中中实现同同样的功能的功能时,可以使用接口。,可以使用接口。23234.3 4.3 接口接口P88 例例4-11显示方式示方式实现接口接口 例例4-12注意:注意:显示示实现接口接口时,不能通,不能通过类的的实例例进行行访问,而必而必须使用接口使用接口实例。例。通通过接口接口实现多多继承承 例例4-
21、132424补充知识:补充知识:C#C#面试题面试题不定不定项选择题(1)(1)以下叙述正确的是:以下叙述正确的是:A.接口中可以有虚方法。接口中可以有虚方法。B.一个一个类可以可以实现多个接口。多个接口。C.接口不能被接口不能被实例化。例化。D.接口中可以包含已接口中可以包含已实现的方法。的方法。B、C(2)以下叙述正确的是:以下叙述正确的是:A.接口和抽象接口和抽象类一一样均只能声明,而不能有均只能声明,而不能有实现部分。部分。B.类可以可以继承多个接口,但承多个接口,但仅能从一个抽象能从一个抽象类或其它或其它类型的型的单个个类继承。承。C.接口中可以定接口中可以定义属性、方法和事件,但只
22、声明不属性、方法和事件,但只声明不实现。D.类的多的多继承可以通承可以通过接口接口实现。B、C、D25254.4 4.4 委托委托类似与似与C+中的函数指中的函数指针,但有很大不同,但有很大不同委托的声明委托的声明例如:例如:public delegate void FuncDelegate(string str););委托的使用委托的使用具体内容不再具体内容不再详细讲述述26264.5 4.5 序列化与反序列化序列化与反序列化序列化序列化获取取对象并将其状象并将其状态信息信息转换为可存可存储或可或可传输形式的形式的过程。程。反序列化反序列化将将对象象还原回序列化之前的内容。原回序列化之前的内
23、容。序列化和反序列化是一个互逆的序列化和反序列化是一个互逆的过程。程。.NET Framework提供的两种序列化技提供的两种序列化技术二二进制序列化制序列化XML和和SOAP序列化序列化27274.5 4.5 序列化与反序列化序列化与反序列化1、如何序列化一个、如何序列化一个类:在:在类的上方加上的上方加上Serializable特性即可。特性即可。Serializable public class MyClass 2、二、二进制序列化制序列化MyClass user=new MyClass();IFormatter formater=new BinaryFormatter();Stream
24、 stream=new FileStream(UserInfo.bin,FileMode.Create,FileAccess.Write,FileShare.None);formater.Serialize(stream,user);stream.Close();特点:特点:二二进制序列化会将一个制序列化会将一个类的所有成的所有成员变量都量都进行序列化,包括私有行序列化,包括私有变量量、公共属性、方法等。、公共属性、方法等。28284.5 4.5 序列化与反序列化序列化与反序列化3、二、二进制反序列化制反序列化IFormatter formatter=new BinaryFormatter()
25、;Stream stream=new FileStream(UserInfo.bin,FileMode.Open,FileAccess.Read,FileShare.Read);MyClass c=(MyClass)formatter.Deserialize(stream);stream.Close();特点:特点:反序列化后,反序列化后,对象象c与序列化之前的状与序列化之前的状态完全相同。完全相同。2929补充:二进制序列化与反序列化举例补充:二进制序列化与反序列化举例保存窗体位置、保存窗体位置、颜色与数据色与数据库连接信息接信息设置置3030补充:二进制序列化与反序列化举例补充:二进制序列
26、化与反序列化举例当当输入服入服务器等信息、改器等信息、改变窗体前景色、位置后,退出窗体前景色、位置后,退出应用程用程序,再次启序,再次启动,可看到仍然是退出前的状,可看到仍然是退出前的状态。31314.5 4.5 序列化与反序列化序列化与反序列化4、XML序列化序列化(1)XML 序列化序列化仅将将对象的公共字段和属性象的公共字段和属性值序列化序列化为XML流,而不流,而不转换方法、方法、索引器、私有字段或只索引器、私有字段或只读属性(只属性(只读集合除外)。集合除外)。(2)XML 序列化不包括序列化不包括类型信息,即不能保型信息,即不能保证序列化后的序列化后的对象在被反序列化象在被反序列化
27、时,变为同一同一类型的型的对象。象。(3)XML序列化的序列化的实现步步骤Class1 user=new Class1();user.AccountName=aa;XmlSerializer mySerializer=new XmlSerializer(typeof(Class1);StreamWriter myWriter=new StreamWriter(UserInfo.xml);mySerializer.Serialize(myWriter,user);myWriter.Close();32324.5 4.5 序列化与反序列化序列化与反序列化(4)XML反序列化的步反序列化的步骤Cla
28、ss1 c;XmlSerializer mySerializer=new XmlSerializer(typeof(Class1);FileStream myFileStream=new FileStream(UserInfo.xml,FileMode.Open);c=(Class1)mySerializer.Deserialize(myFileStream);myFileStream.Close();注意:注意:反序列化一个反序列化一个对象象时不会不会调用构造函数,用构造函数,这一点与一点与创建建对象不同。象不同。33334.6 4.6 泛型处理泛型处理 泛型(泛型(Generic)一般用在
29、集合和在集合上运行的方法中)一般用在集合和在集合上运行的方法中。.NET框架框架2.0以前的版本不支持泛型。以前的版本不支持泛型。使用泛型具有以下明使用泛型具有以下明显的的优点点:1)可以避免以下两个可以避免以下两个问题:内部:内部实现代代码冗余和困冗余和困扰开开发人人员的含混不清的的含混不清的编译器器错误提示提示;2)类型安全型安全;3)二二进制代制代码重用重用;4)性能性能;5)清晰性。清晰性。34344.64.6 泛型问题描述泛型问题描述public class Stack object m_Items;public void Push(object item).public objec
30、t Pop().使用使用举例:例:Stack stack=new Stack();stack.Push(1);int number=(int)stack.Pop();stack.Push(“str”);string str=(string)stack.Pop();3535基于基于ObjectObject的堆栈缺点的堆栈缺点性能性能问题值类型需型需频繁地装箱、拆箱,造成繁地装箱、拆箱,造成较多的垃圾碎片,增多的垃圾碎片,增加垃圾回收的加垃圾回收的负担担引用引用类型需要型需要强制制类型型转换类型安全型安全问题(更(更严重)重)编译时任任务类型都型都转换成成object,无法保,无法保证运行运行时类
31、型型安全。安全。例如:例如:Stack stack=new Stack();stack.Push(“abc”);int number=(int)stack.Pop();36364.6 4.6 泛型解决办法泛型解决办法public class IntStack int m_Items;public void Push(int item).public int Pop().public class StringStack public class StringStack string m_Items;string m_Items;public void Push(string item)publi
32、c void Push(string item).public string Pop()public string Pop().功能相似,代码冗余!维护麻烦!3737基于基于Object的的堆堆栈IntStackStringStack代码冗余,维护复杂,工作效率低性能问题、类型安全问题有没有好的解决办法?有,泛型3838解决方法采用泛型解决方法采用泛型public class Stack T m_Items;public void Push(T item).public T Pop().3939泛型是如何实现的?泛型是如何实现的?在在.NET 2.0中,泛型在中,泛型在IL(中(中间语言)和言
33、)和CLR本身中本身中具有本机支持具有本机支持编译泛型泛型时,就像,就像编译类一一样,泛型,泛型仅保留保留一个一个占位符占位符。而用特定而用特定类型型实例化的泛型代例化的泛型代码,编译时会会将泛型替将泛型替换为实例化的特定例化的特定类型。型。4040泛型实现泛型实现public class Stack T m_Items;public void Push(T item).public T Pop().使用使用举例:例:Stack stack=new Stackstack.Push(1);int number=stack.Pop();4141泛型的定义和引用泛型的定义和引用泛型定泛型定义代代码语
34、法如下:法如下:访问修修饰符符返回返回类型型 泛型支持泛型支持类型型 泛型名称泛型名称 其中其中CLR支持的泛型支持的泛型类、结构、方法、接口和委托等。构、方法、接口和委托等。泛型泛型类定定义举例:例:class Node T data;Node next;例例4-19 引用泛型引用泛型类4242泛型的引用泛型的引用泛型泛型类定定义举例:例:void Swap(ref T item1,ref T item2)T temp=item1;item1=item2;item2=temp;例例4-20 引用一个泛型方法引用一个泛型方法程序程序举例:使用泛型方法来例:使用泛型方法来实现int、double
35、、float类型的型的数据交数据交换方法。方法。4343常用泛型常用泛型凡是有凡是有对应泛型泛型类型的型的类就尽量不要使用早期提供的非泛就尽量不要使用早期提供的非泛型型类型的型的类。下面的泛型。下面的泛型类型型对应于低版本提供的于低版本提供的类型:型:泛型泛型类低版本提供的非泛型低版本提供的非泛型类List ArrayList Dictionary Hashtable Queue Queue Stack Stack SortedList SortedList4444实验中用到的泛型实验中用到的泛型SortedList:按:按键排序的排序的键值对集合,是运算复集合,是运算复杂度度为 O(log
36、n)的二的二进制搜索制搜索树。常用方法:常用方法:Add方法:将方法:将带有指定有指定键和和值的元素添加到的元素添加到SortedList 中中 例如(注意:如果插入重复的例如(注意:如果插入重复的键会会产生异常):生异常):SortedList openWith=new SortedList();openWith.Add(txt,notepad.exe);openWith.Add(bmp,paint.exe);4545实验中用到的泛型(续)实验中用到的泛型(续)如何遍如何遍历泛型列表中的每个泛型列表中的每个键值对SortedList list=new SortedList();list.Ad
37、d(a,123);list.Add(b,234);list.Add(c,456);foreach(string str in list.Keys)Console.WriteLine(key is:+str+,value is:+liststr.ToString();4646实验中用到的泛型(续)实验中用到的泛型(续)TryGetValue方法:方法:获取与指定的取与指定的键相关相关联的的值。例如:例如:string value=;if(openWith.TryGetValue(tif,out value)Console.WriteLine(For key=tif,value=0.,value)
38、;else Console.WriteLine(Key=tif is not found.);4747实验中用到的泛型(续)实验中用到的泛型(续)ContainsKey 方法:确定方法:确定 SortedList中中 是否包含指定的是否包含指定的键。例如:例如:if(!openWith.ContainsKey(ht)openWith.Add(ht,hypertrm.exe);Console.WriteLine(Value added for key=ht:0,openWithht);4848实验中用到的泛型(续)实验中用到的泛型(续)Remove 方法:从方法:从SortedList 中移除中
39、移除带有指定有指定键的元素。的元素。例如:例如:openWith.Remove(doc);if(openWith.ContainsKey(doc)=false)Console.WriteLine(Key doc is not found.);4949本章小结本章小结面向面向对象的三大特性:封装、象的三大特性:封装、继承和多承和多态在在扩充充类中中调用基用基类构造函数、方法构造函数、方法重写基重写基类的方法、属性的方法、属性隐藏基藏基类的方法、属性的方法、属性版本控制版本控制接口定接口定义和和调用用泛型泛型类SortedList的用法的用法其余内容了解其余内容了解5050综合举例综合举例图形绘制
40、图形绘制图形抽象基形抽象基类Shapepublic abstract class Shape椭圆类Ellipsepublic class Ellipse:Shape矩形矩形类Rectanglepublic class Rectangle:Shape三角形三角形类Trianglepublic class Triangle:Shape.为每个每个类提供一个画提供一个画图的方法的方法Draw()和求面和求面积的方法的方法GetArea()5151运行结果运行结果5252读程序写结果读程序写结果public class Apublic virtual void Fun1(int i)Console.WriteLine(i);public void Fun2(A a)a.Fun1(1);Fun1(5);public class B:Apublic override void Fun1(int i)base.Fun1(i+1);MainMain方法中:方法中:A A a anew A();new A();B b=new B();B b=new B();a.Fun2(b);a.Fun2(b);问输出结果是什么?问输出结果是什么?2 2 5 55353本章作业及实验本章作业及实验本章作本章作业:P106 5、6 本章本章结束后可以做束后可以做实验三三