您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 其它文档 > Net面向对象程序设计-13-创建接口和定义抽象类-2010-2011-2.
.NET面向对象程序设计第13章创建接口和定义抽象类本章简介定义接口在结构或类中实现接口通过接口引用一个类在抽象类中捕获通用的实现细节使用sealed关键字13.2抽象类存在的问题:MoveForward方法仅仅是一个哑方法,它需要在子类中进行覆盖,如果放置了错误的方法而又有人调用,问题严重!19:publicvirtualvoidMoveForward()20:{21:Console.Write(Movingforward...);22:odometer+=1;23:Console.WriteLine(Odometerreading:{0},odometer);24:}解决:使用抽象方法一个抽象方法只包含方法头而且没有实现代码,它需要后续类来具体实现这一方法。当一个类包含一个或多个抽象方法时,此类必须声明为abstract。一个抽象类不能实例化,因为它包含没有实现的方法。示例:AbstractMoveForward.cs01: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:}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:}SyntaxBox:AbstractMethodAbstract_method::=[Method_modifiers]abstractReturn_typeMethod_identifier([Formal_parameter_list]);Abstract_property_1::=[Property_modifiers]abstractReturn_typeProperty_identifier{[get;][set;]}Abstract_indexer_1::=[Indexer_modifiers]abstract[Return_type]this[Parameter_list]{[get;][set;]}Abstract_class::=Class_modifiersabstractClass_name{Class_members}说明:用关键字abstract声明的抽象方法没有方法体,在一对包括形式参数列表的圆括号后面有一个分号。抽象方法不能声明为private、static、virtual抽象方法和抽象存取器为隐式的virtual抽象方法只能存在于抽象类中,但抽象类能包括非抽象方法抽象类不能实例化从一个包含抽象方法的类中派生一个类,派生类也成为抽象,除非覆盖从基类中继承的所有抽象方法并提供实现语句。在派生类中可以使用抽象方法来覆盖虚方法,任何从此抽象类派生的类必须覆盖这些抽象方法并提供新的实现语句,使之变成非抽象。9生活中的接口电脑主板上的PCI插槽的规范就类似于C#接口声卡显卡网卡每种卡的内部结构都不相同,可以把声卡、网卡、显卡都插在PCI插槽上,而不用担心哪个插槽是专门插哪个卡的主板13.1理解接口关于多重继承的争议多重继承可以让类拥有多个基类当两个基类都包含一个信号相同但实现过程不同的方法或属性时发生的情况:moveforward、brandName、odometerC#禁止多重继承而用另一种语言结构:接口来解决问题。13.1.1定义接口接口是表示一组函数成员而不实现成员的引用类型C#中使用interface定义接口注意:C#中建议接口名以大写字母I开头13.1.2实现接口•要实现一个接口,需要声明一个类或结构,让它们从接口继承,并实现接口指定的全部方法例如:interfaceILandBound{intNumberOfLegs();}•然后可以在Horse类中实现该接口classHorse:ILandBound{...publicintNumberOfLegs(){return4;}}实现一个接口时,必须保证每个方法都完全匹配与它对应的接口中的方法,规则如下:方法名和返回类型完全匹配所有参数(包括ref和out关键字)完全匹配使用接口名作为方法的前缀,称之为显式接口实现,尽量使用显式接口实现用于实现一个接口的所有方法都必须具有public可访问性,但是,如果使用显式接口实现,则不应该为方法添加访问修饰符接口的定义和实现存在任何差异,类都无法编译一个类可以在扩展另一个类的同时实现一个接口下例将Horse定义成从Mammal继承的一个类,同时实现了ILandBound接口interfaceILandBound{...}classMammal{...}classHorse:Mammal,ILandBound{...}13.1.3通过接口来引用一个类可以把一个变量定义成引用层次结构中较高位置的一个类,然后用这个变量引用对象类似的,可以将一个变量定义成类所实现的接口,然后用这个变量引用对象例如:HorsemyHorse=newHorse(...);ILandBoundiMyHorse=myHorse;//legal通过接口来引用一个对象,是一项相当有用的技术我们能由此定义方法,让它获得不同的类型作为参数,只要类型实现了指定的接口intFindLandSpeed(ILandBoundlandBoundMammal){...}13.1.4使用多个接口一个类最多只能有一个基类,但可以实现数量无限的接口类必须实现它从它的所有接口继承的所有方法例如:classHorse:Mammal,ILandBound,IGrazable{...}13.1.5显式实现接口Horse类实现了ILandBound接口,但在Horse的NumberOfLegs方法中,没有任何地方说它是ILandBound接口的一部分interfaceILandBound{intNumberOfLegs();}classHorse:ILandBound{...publicintNumberOfLegs(){return4;}}如果Horse类实现了多个接口,而多个接口指定了同名的方法,则会出现歧义例如:interfaceIJourney{intNumberOfLegs();}classHorse:ILandBound,IJourney{...publicintNumberOfLegs(){return4;}}C#中通过显式实现接口解决这个问题为此,要在实现一个接口时,指明方法从属于该接口classHorse:ILandBound,IJourney{...intILandBound.NumberOfLegs(){return4;}intIJourney.NumberOfLegs(){return3;}}注意:方法没有用public标记。如果方法是显式接口实现的一部分,就不能为方法指定访问修饰符,所以无法从类的外部访问。如果方法在Horse类中可见,下述代码无法确定Horsehorse=newHorse();...intlegs=horse.NumberOfLegs();应该通过恰当的接口来引用Horse对象Horsehorse=newHorse();...IJourneyjourneyHorse=horse;intlegsInJourney=journeyHorse.NumberOfLegs();ILandBoundlandBoundHorse=horse;intlegsOnHorse=landBoundHorse.NumberOfLegs();abstractclass与interface抽象类(abstractclass)是一种特殊的类抽象方法只做声明,而不包含实现,可以看成是没有实现体的虚方法抽象类不能被实例化,除此之外,具有类的其他特性抽象类可以但不是必须有抽象属性和抽象方法,但是一旦有了抽象方法,就一定要把这个类声明为抽象类具体派生类必须覆盖基类的抽象方法抽象类可以派生自另一个抽象类,可以覆盖基类的抽象方法也可以不覆盖,如果不覆盖,则其派生类必须覆盖它们接口:是引用类型,类似于抽象类但又不同于抽象类不能被实例化只能包含实现的方法声明成员可以包括方法、属性、索引器和事件接口中不能包含常量、字段、构造函数、析构函数或静态成员接口中的所有成员默认为public,接口中不能有private成员派生类必须实现接口的所有成员一个类可以实现多个接口一个接口可以有多个父接口,实现该接口必须实现多有父接口中的所有成员抽象类和接口的共同点都可以被继承都不能被实例化都可以包含方法声明派生类必须实现未实现的方法抽象类和接口的区别抽象类是一个不完整的类,需要进一步细化,而接口只是一个行为规范或规定,微软的自定义接口总是后带able字段,证明其是表述一类类“我能做…”.抽象类可以定义字段、属性和方法实现。接口只能定义属性、索引器、事件、和方法声明,不能包含字段。抽象类更多的是定义在一系列紧密相关的类之间,而接口大多数是定义在关系疏松但都实现某一功能的类中。接口基本上不具备继承的任何具体特点,它仅仅承诺了能够调用的方法。接口可以被多重实现,抽象类只能被单一继承。即一个类一次可以实现若干个接口,但只能继承一个父类。接口可以用于支持回调,而继承并不具备这个特点。抽象类不能被密封。抽象类实现的具体方法默认为虚的,但实现接口类的接口方法却默认为非虚的,当然也可以声明为虚的。接口与非抽象类类似,抽象类也必须为在该类的基类表中列出接口的所有成员提供它自己的实现。但是,允许抽象类将接口方法映射到抽象方法上。如果抽象类实现接口,则可以把接口中的方法映射到抽象类中作为抽象方法而不必实现,而在抽象类的子类中实现接口的方法。抽象类和接口的使用抽象类主要用于关系密切的对象;而接口用于为不相关的类提供通用功能如果要设计大的功能单元,则使用抽象类;如果要在组件的所有实现间提供通用的已实现功能,则使用抽象类。如果创建的功能将在大范围的全异对象间使用,则使用接口。如果要设计小而简练的功能块,则使用接口。如果预计要创建组件的多个版本,则创建抽象类。抽象类提供简单的方法来控制组件版本。好的接口定义应该是具有专一功能性的,而不是多功能的,否则会造成接口的污染。如果一个类只是实现了这个接口中的一个功能,而不得不去实现接口的其他方法,那么就叫接口污染。
本文标题:Net面向对象程序设计-13-创建接口和定义抽象类-2010-2011-2.
链接地址:https://www.777doc.com/doc-2889594 .html