面向对象程序设计创建接口和定义抽象类详解演示文稿_第1页
面向对象程序设计创建接口和定义抽象类详解演示文稿_第2页
面向对象程序设计创建接口和定义抽象类详解演示文稿_第3页
面向对象程序设计创建接口和定义抽象类详解演示文稿_第4页
面向对象程序设计创建接口和定义抽象类详解演示文稿_第5页
已阅读5页,还剩30页未读 继续免费阅读

下载本文档

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

文档简介

面向对象程序设计创建接口和定义抽象类详解演示文稿现在是1页\一共有35页\编辑于星期五优选面向对象程序设计创建接口和定义抽象类现在是2页\一共有35页\编辑于星期五13.2抽象类存在的问题:MoveForward方法仅仅是一个哑方法,它需要在子类中进行覆盖,如果放置了错误的方法而又有人调用,问题严重!19:publicvirtualvoidMoveForward()20:{21:Console.Write("Movingforward...");22:odometer+=1;23:Console.WriteLine("Odometerreading:{0}",odometer);24:}现在是3页\一共有35页\编辑于星期五解决:使用抽象方法一个抽象方法只包含方法头而且没有实现代码,它需要后续类来具体实现这一方法。当一个类包含一个或多个抽象方法时,此类必须声明为abstract。一个抽象类不能实例化,因为它包含没有实现的方法。现在是4页\一共有35页\编辑于星期五示例:AbstractMoveForward.cs

01:usingSystem;02:03:abstractclassCar04:{05:privateuintodometer=0;06:07:protecteduintOdometer08:{09:set10:{11:odometer=value;12:}13:get14:{15:returnodometer;16:}17:}18:19:publicabstractvoidMoveForward();20:}现在是5页\一共有35页\编辑于星期五22:classRacingCar:Car23:{24:publicoverridevoidMoveForward()25:{26:Console.Write("Movingdangerouslyfastforward...");27:Odometer+=30;28:Console.WriteLine("Odometerinracingcar:{0}",Odometer);29:}30:}32:classFamilyCar:Car33:{34:publicoverridevoidMoveForward()35:{36:Console.Write("Movingslowlybutsafelyforward...");37:Odometer+=5;38:Console.WriteLine("Odometerinfamilycar:{0}",Odometer);39:}40:}42:classCarTester43:{44:publicstaticvoidMain()45:{46:RacingCarmyRacingCar=newRacingCar();47:FamilyCarmyFamilyCar=newFamilyCar();48:myRacingCar.MoveForward();49:myFamilyCar.MoveForward();50:}51:}现在是6页\一共有35页\编辑于星期五SyntaxBox:AbstractMethodAbstract_method::=[<Method_modifiers>]abstract<Return_type>

<Method_identifier>([<Formal_parameter_list>]);Abstract_property_1::=

[<Property_modifiers>]abstract<Return_type><Property_identifier>{

[get;]

[set;]}Abstract_indexer_1::=

[<Indexer_modifiers>]abstract[<Return_type>]this[<Parameter_list>]{

[get;]

[set;]}Abstract_class::=

<Class_modifiers>abstract<Class_name>{

<Class_members>}现在是7页\一共有35页\编辑于星期五说明:用关键字abstract声明的抽象方法没有方法体,在一对包括形式参数列表的圆括号后面有一个分号。抽象方法不能声明为private、static、virtual抽象方法和抽象存取器为隐式的virtual抽象方法只能存在于抽象类中,但抽象类能包括非抽象方法抽象类不能实例化从一个包含抽象方法的类中派生一个类,派生类也成为抽象,除非覆盖从基类中继承的所有抽象方法并提供实现语句。在派生类中可以使用抽象方法来覆盖虚方法,任何从此抽象类派生的类必须覆盖这些抽象方法并提供新的实现语句,使之变成非抽象。现在是8页\一共有35页\编辑于星期五9生活中的接口电脑主板上的PCI插槽的规范就类似于C#接口声卡显卡网卡每种卡的内部结构都不相同,可以把声卡、网卡、显卡都插在PCI插槽上,而不用担心哪个插槽是专门插哪个卡的主板现在是9页\一共有35页\编辑于星期五13.1理解接口关于多重继承的争议多重继承可以让类拥有多个基类当两个基类都包含一个信号相同但实现过程不同的方法或属性时发生的情况:moveforward、brandName、odometerC#禁止多重继承而用另一种语言结构:接口来解决问题。现在是10页\一共有35页\编辑于星期五13.1.1定义接口接口是表示一组函数成员而不实现成员的引用类型C#中使用interface定义接口注意:C#中建议接口名以大写字母I开头现在是11页\一共有35页\编辑于星期五实现接口要实现一个接口,需要声明一个类或结构,让它们从接口继承,并实现接口指定的全部方法例如:interfaceILandBound{intNumberOfLegs();}然后可以在Horse类中实现该接口classHorse:ILandBound{...publicintNumberOfLegs(){return4;}}现在是12页\一共有35页\编辑于星期五实现一个接口时,必须保证每个方法都完全匹配与它对应的接口中的方法,规则如下:方法名和返回类型完全匹配所有参数(包括ref和out关键字)完全匹配使用接口名作为方法的前缀,称之为显式接口实现,尽量使用显式接口实现用于实现一个接口的所有方法都必须具有public可访问性,但是,如果使用显式接口实现,则不应该为方法添加访问修饰符接口的定义和实现存在任何差异,类都无法编译现在是13页\一共有35页\编辑于星期五一个类可以在扩展另一个类的同时实现一个接口下例将Horse定义成从Mammal继承的一个类,同时实现了ILandBound接口interfaceILandBound{...}classMammal{...}classHorse:Mammal,ILandBound{...}现在是14页\一共有35页\编辑于星期五13.1.3通过接口来引用一个类可以把一个变量定义成引用层次结构中较高位置的一个类,然后用这个变量引用对象类似的,可以将一个变量定义成类所实现的接口,然后用这个变量引用对象例如:HorsemyHorse=newHorse(...);ILandBoundiMyHorse=myHorse;//legal通过接口来引用一个对象,是一项相当有用的技术我们能由此定义方法,让它获得不同的类型作为参数,只要类型实现了指定的接口intFindLandSpeed(ILandBoundlandBoundMammal){...}现在是15页\一共有35页\编辑于星期五13.1.4使用多个接口一个类最多只能有一个基类,但可以实现数量无限的接口类必须实现它从它的所有接口继承的所有方法例如:classHorse:Mammal,ILandBound,IGrazable{...}现在是16页\一共有35页\编辑于星期五13.1.5显式实现接口Horse类实现了ILandBound接口,但在Horse的NumberOfLegs方法中,没有任何地方说它是ILandBound接口的一部分interfaceILandBound{intNumberOfLegs();}classHorse:ILandBound{...publicintNumberOfLegs(){return4;}}如果Horse类实现了多个接口,而多个接口指定了同名的方法,则会出现歧义例如:interfaceIJourney{intNumberOfLegs();}classHorse:ILandBound,IJourney{...publicintNumberOfLegs(){return4;}}现在是17页\一共有35页\编辑于星期五C#中通过显式实现接口解决这个问题为此,要在实现一个接口时,指明方法从属于该接口classHorse:ILandBound,IJourney{...intILandBound.NumberOfLegs(){return4;}intIJourney.NumberOfLegs(){return3;}}注意:方法没有用public标记。如果方法是显式接口实现的一部分,就不能为方法指定访问修饰符,所以无法从类的外部访问。现在是18页\一共有35页\编辑于星期五如果方法在Horse类中可见,下述代码无法确定Horsehorse=newHorse();...intlegs=horse.NumberOfLegs();应该通过恰当的接口来引用Horse对象Horsehorse=newHorse();...IJourneyjourneyHorse=horse;intlegsInJourney=journeyHorse.NumberOfLegs();ILandBoundlandBoundHorse=horse;intlegsOnHorse=landBoundHorse.NumberOfLegs();现在是19页\一共有35页\编辑于星期五abstractclass与interface抽象类(abstractclass)是一种特殊的类抽象方法只做声明,而不包含实现,可以看成是没有实现体的虚方法抽象类不能被实例化,除此之外,具有类的其他特性抽象类可以但不是必须有抽象属性和抽象方法,但是一旦有了抽象方法,就一定要把这个类声明为抽象类具体派生类必须覆盖基类的抽象方法抽象类可以派生自另一个抽象类,可以覆盖基类的抽象方法也可以不覆盖,如果不覆盖,则其派生类必须覆盖它们接口:是引用类型,类似于抽象类但又不同于抽象类不能被实例化只能包含实现的方法声明成员可以包括方法、属性、索引器和事件接口中不能包含常量、字段、构造函数、析构函数或静态成员接口中的所有成员默认为public,接口中不能有private成员派生类必须实现接口的所有成员一个类可以实现多个接口一个接口可以有多个父接口,实现该接口必须实现多有父接口中的所有成员现在是20页\一共有35页\编辑于星期五抽象类和接口的共同点都可以被继承都不能被实例化都可以包含方法声明派生类必须实现未实现的方法现在是21页\一共有35页\编辑于星期五抽象类和接口的区别抽象类是一个不完整的类,需要进一步细化,而接口只是一个行为规范或规定,微软的自定义接口总是后带able字段,证明其是表述一类类“我能做…”.抽象类可以定义字段、属性和方法实现。接口只能定义属性、索引器、事件、和方法声明,不能包含字段。抽象类更多的是定义在一系列紧密相关的类之间,而接口大多数是定义在关系疏松但都实现某一功能的类中。接口基本上不具备继承的任何具体特点,它仅仅承诺了能够调用的方法。接口可以被多重实现,抽象类只能被单一继承。即一个类一次可以实现若干个接口,但只能继承一个父类。接口可以用于支持回调,而继承并不具备这个特点。抽象类不能被密封。抽象类实现的具体方法默认为虚的,但实现接口类的接口方法却默认为非虚的,当然也可以声明为虚的。接口与非抽象类类似,抽象类也必须为在该类的基类表中列出接口的所有成员提供它自己的实现。但是,允许抽象类将接口方法映射到抽象方法上。如果抽象类实现接口,则可以把接口中的方法映射到抽象类中作为抽象方法而不必实现,而在抽象类的子类中实现接口的方法。现在是22页\一共有35页\编辑于星期五抽象类和接口的使用抽象类主要用于关系密切的对象;而接口用于为不相关的类提供通用功能如果要设计大的功能单元,则使用抽象类;如果要在组件的所有实现间提供通用的已实现功能,则使用抽象类。如果创建的功能将在大范围的全异对象间使用,则使用接口。如果要设计小而简练的功能块,则使用接口。如果预计要创建组件的多个版本,则创建抽象类。抽象类提供简单的方法来控制组件版本。好的接口定义应该是具有专一功能性的,而不是多功能的,否则会造成接口的污染。如果一个类只是实现了这个接口中的一个功能,而不得不去实现接口的其他方法,那么就叫接口污染。尽量避免使用继承来实现组件功能,而是使用黑箱复用,即对象组合。因为继承的层次增多,造成最直接的后果就是当你调用这个类群中的某一类时,就必须把它们全部加载到栈中!后果可想而知。同时,有心的朋友可以留意到微软在构建一个类时,很多时候都用到了对象组合的方法。比如中的\Page类,有Server、Request等属性,但其实它们都是某个类的对象。使用Page类的这个对象来调用另外类的方法和属性,是非常基本的一个设计原则。现在是23页\一共有35页\编辑于星期五2413.1.6接口的限制不允许在接口中定义任何字段,即使是静态字段。字段本质上是类或结构的一种实现细节不允许在接口中定义任何构造器不允许在接口中定义任何析构器不允许为任何方法指定访问修饰符,接口中的所有方法都隐式为public不允许在接口中嵌套任何类型虽然一个接口能从另一个接口继承,但不允许从结构或者类中继承一个接口。结构或者类中含有实现,假如允许接口从它们继承,就会继承一些实现。说明:接口标示符习惯上以大写I开头,因为接口可以强迫类实现抽象成员让类执行额外的动作,所以类标识符通常以able结尾。总之:接口描述需要实现的操作、属性和事件,以及每个操作需要接受和返回的参数类型,但将操作的特定实现留给实现接口的类去完成。现在是24页\一共有35页\编辑于星期五25接口的一个应用在一个类层次中要实现多态,必需具备一组有相同祖先的类如果我们想要划分成组的类不具有相同的祖先呢?如果它们分布于整个程序的多个地方,甚至位于多个单独的类层次中,情况如何??现在是25页\一共有35页\编辑于星期五26现在是26页\一共有35页\编辑于星期五27实现方法:publicinterfaceIDrawable{voidDrawYourself();}现在是27页\一共有35页\编辑于星期五28示例程序:ComparableTimeSpans.cs01:usingSystem;02:03:publicinterfaceIComparable04:{05:intCompareTo(IComparablecomp);06:}07:08:publicclassTimeSpan:IComparable09:{10:privateuinttotalSeconds;11:12:publicTimeSpan()13:{14:totalSeconds=0;15:}16:17:publicTimeSpan(uintinitialSeconds)18:{19:totalSeconds=initialSeconds;20:}现在是28页\一共有35页\编辑于星期五2922:publicuintSeconds23:{24:get25:{26:returntotalSeconds;27:}28:29:set30:{31:totalSeconds=value;32:}33:}34:35:publicintCompareTo(IComparablecomp)36:{37:TimeSpancompareTime=(TimeSpan)comp;38:39:if(totalSeconds>compareTime.Seconds)40:return1;41:elseif(compareTime.Seconds==totalSeconds)42:return0;43:else44:return-1;45:}46:}现在是29页\一共有35页\编辑于星期五3048:classTester49:{50:publicstaticvoidMain()51:{52:TimeSpanmyTime=newTimeSpan(3450);53:TimeSpanworldRecord=newTimeSpan(1239);54:55:if(myTime.CompareTo(worldRecord)<0)56:Console.WriteLine("Mytimeisbelowtheworldrecord");57:elseif(myTime.CompareTo(worldRecord)==0)58:Console.WriteLine("Mytimeisthesameastheworldrecord");59:else60:Console.WriteLine("Ispentmoretimethantheworldrecordholder");61:}62:}Ispentmoretimethantheworldrecordholder现在是30页\一共有35页\编辑于星期五31接口的另一个应用示例排序的实现:按姓名排序、分数、院系一般性的实现过程:可重用于排序其他任何对象类型示例:BubbleSortAscening.cs现在是31页\一共有35页\编辑于星期五3201://Sorttheelementsofanarrayinascendingorder02:publicstaticvoidBubbleSortAscending(int[]bubbles)03:{04:boolswapped=true;05:06:for(inti=0;swapped;i++)07:{08:swapped=false;09:for(intj=0;j<(bubbles.Length-(i+1));j++)10:{11:if(bubbles[j]>bubbles[j+1])12:{13:Swap(j,j+1,bubbles);14:swapped=true;15:}16:}17:}18:}19:20://Swaptwoelementsofanarray21:publicstaticvoidSwap(intfirst,intsecond,int[]arr)22:{23:inttemp;24:25:temp=arr[first];26:arr[first]=arr[second];27:arr[second]=temp;28:}现在是32页\一共有35页\编辑于星期五33存在的问题:只能排序元素类型为int的数组思考:只有11行涉及到更换数组元素类型,其余代码可以保持不变,使用替换代码if(bubbles[j].CompareTo(bubbles[j+1])>0)实现:将一般排序方法的形式参数声明为Icomparable类型的数组,可以确定只有包含可比较对象的数组被传递给方法现在是33页\一共有35页\编辑于星期五3401:usingSystem;02:03:publicinterfaceIComparable04:{05:intCompareTo(IComparablecomp);06:}07:08:publicclassTimeSpan:IComparable09:{10:privateuinttotalSeconds;11:12:publicTimeSpan()13:{14:totalSeconds=0;15:}16:17:publicTimeSpan(uintinitialSeconds)18:{19:totalSeconds=initialSeconds;20:}22:publicuintSeconds23:{24:get25:{26:returntotalSeconds;27:}28:29:set30:{31:totalSeconds=value;32:}33:}34:35:publicvirtualintCompareTo(IComparablecomp)36:{37:TimeSpancompareTime=(TimeSpan

温馨提示

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

评论

0/150

提交评论