.net中接口和抽象类的区别x

上传人:苏美尔 文档编号:8846980 上传时间:2021-01-19 格式:DOCX 页数:10 大小:17.80KB
返回 下载 相关 举报
.net中接口和抽象类的区别x_第1页
第1页 / 共10页
.net中接口和抽象类的区别x_第2页
第2页 / 共10页
.net中接口和抽象类的区别x_第3页
第3页 / 共10页
.net中接口和抽象类的区别x_第4页
第4页 / 共10页
.net中接口和抽象类的区别x_第5页
第5页 / 共10页
点击查看更多>>
资源描述

《.net中接口和抽象类的区别x》由会员分享,可在线阅读,更多相关《.net中接口和抽象类的区别x(10页珍藏版)》请在三一文库上搜索。

1、Net中抽象类和接口的区别 一、抽象类 (1) 抽象方法只作声明,而不包含实现,可以看成是没有实现体的虚方法 (2) 抽象类不能被实例化 (3) 抽象类可以但不是必须有抽象属性和抽象方法,但是一旦有了抽象方法,就一定要把这个类声明为抽象类 (4) 具体派生类必须覆盖基类的抽象方法 (5) 抽象派生类可以覆盖基类的抽象方法,也可以不覆盖。如果不覆盖,则其具体派生类必须覆盖它们。如:using System;public abstract class A /抽象类A private int num=0; public int Num /抽象类包含属性 get return num; set num

2、 = value; public virtual int getNum() /抽象类包含虚方法 return num; public void setNum(int n) / /抽象类包含普通方法 this.num = n; public abstract void E(); /类A中的抽象方法E public abstract class B : A /由于类B继承了类A中的抽象方法E,所以类B也变成了抽象类 public class C : B public override void E() /重写从类A继承的抽象方法。如果类B自己还定义了抽象方法,也必须重写 /throw new Ex

3、ception(The method or operation is not implemented.); public class Test static void Main() C c = new C(); c.E(); 二、接 口 (1) 接口不能被实例化 (2) 接口只能包含方法声明 (3) 接口的成员包括方法、属性、索引器、事件 (4) 接口中不能包含常量、字段(域)、构造函数、析构函数、静态成员。如:public delegate void EventHandler(object sender, Event e);public interface ITest /int x = 0;

4、 int A get; set; void Test(); event EventHandler Event; int thisint index get; set; (5) 接口中的所有成员默认为public,因此接口中不能有private修饰符 (6) 派生类必须实现接口的所有成员 (7) 一个类可以直接实现多个接口,接口之间用逗号隔开 (8) 一个接口可以有多个父接口,实现该接口的类必须实现所有父接口中的所有成员三、抽象类和接口 相同点: (1) 都可以被继承 (2) 都不能被实例化 (3) 都可以包含方法声明 (4) 派生类必须实现未实现的方法 区 别: (1) 抽象基类可以定义字段、

5、属性、方法实现。接口只能定义属性、索引器、事件、和方法声明,不能包含字段。 (2) 抽象类是一个不完整的类,需要进一步细化,而接口是一个行为规范。微软的自定义接口总是后带able字段,证明其是表述一类“我能做。” (3) 接口可以被多重实现,抽象类只能被单一继承 (4) 抽象类更多的是定义在一系列紧密相关的类间,而接口大多数是关系疏松但都实现某一功能的类中 (5) 抽象类是从一系列相关对象中抽象出来的概念, 因此反映的是事物的内部共性;接口是为了满足外部调用而定义的一个功能约定, 因此反映的是事物的外部特性 (6) 接口基本上不具备继承的任何具体特点,它仅仅承诺了能够调用的方法 (7) 接口可

6、以用于支持回调,而继承并不具备这个特点 (8) 抽象类实现的具体方法默认为虚的,但实现接口的类中的接口方法却默认为非虚的,当然您也可以声明为虚的 (9) 如果抽象类实现接口,则可以把接口中方法映射到抽象类中作为抽象方法而不必实现,而在抽象类的子类中实现接口中方法 使用规则: 1、抽象类主要用于关系密切的对象,而接口最适合为不相关的类提供通用功能 2、如果要设计大的功能单元,则使用抽象类;如果要设计小而简练的功能块,则使用接口。 3、如果预计要创建组件的多个版本,则创建抽象类。接口一旦创建就不能更改。如果需要接口的新版本,必须创建一个全新的接口。 4、如果创建的功能将在大范围的全异对象间使用,则

7、使用接口;如果要在组件的所有实现间提供通用的已实现功能,则使用抽象类。 5、分析对象,提炼内部共性形成抽象类,用以表示对象本质,即“是什么”。为外部提供调用或功能需要扩充时优先使用接口 6、好的接口定义应该是具有专一功能性的,而不是多功能的,否则造成接口污染。如果一个类只是实现了这个接口的中一个功能,而不得不去实现接口中的其他方法,就叫接口污染 7、尽量避免使用继承来实现组建功能,而是使用黑箱复用,即对象组合。因为继承的层次增多,造成最直接的后果就是当你调用这个类群中某一类,就必须把他们 全部加载到栈中!后果可想而知。(结合堆栈原理理解)。同时,有心的朋友可以留意到微软在构建一个类时,很多时候

8、用到了对象组合的方法。比如 中,Page类,有Server Request等属性,但其实他们都是某个类的对象。使用Page类的这个对象来调用另外的类的方法和属性,这个是非常基本的一个设计原则 例 如: Window窗体可以用抽象类来设计,可以把公有操作和属性放到一个抽象类里,让窗体和对话框继承自这个抽象类,再根据自己的需求进行扩展和完善。 打印操作可以作为一个接口提供给每个需要此功能的窗体,因为窗体的内容不同,就要根据他们自己的要求去实现自己的打印功能。打印时只通过接口来调用,而不用在乎是那个窗体要打印。四、其它文章 共性、个性与选择 有的书上写到C#推荐使用接口(Interface)来替代抽

9、象基类(Abstract Class),并强调使用接口的诸多好处,这点我不敢苟同,从上面列表中看来,两者之间还是存在不少差异的,而这种差异的存在性必然决定了适用场景的不 同,例如在抽象基类中可以为部分方法提供默认的实现,从而避免在子类中重复实现它们,提高代码的可重用性,这是抽象类的优势所在;而接口中只能包含抽象方 法。至于何时使用抽象基类何时使用接口关键还是取决于用户是如何看待继承类之间的联系的,用户更加关心的是它们之间的个性差异还是它们之间的共性联系。举 个生活中的例子加以说明。 如果给你三个对象分别是人、鱼、青蛙,让你为他们设计个基类来概括它们之间的联系,那么首先给你的感觉肯定是它们个体间

10、的差异性较大,很难抽象出共性,然 而若让你概括他们行为之间的共性,你可能想了想会意识到他们都会游泳,只不过是游泳方式迥异。那么这时你就应当考虑使用接口而不是抽象基类,原因有三条: 1. 个性大于共性。 2. 差异较大的个性间具有某些相同的行为。 3. 相同行为的实现方式有较大区别。 这时再给你三个对象,分别是鲫鱼、鲤鱼、金鱼,仍然让你设计基类来概括它们之间的联系,那么你第一个意识到的肯定是它们都属于鱼类,其次是他们游泳的方式可能稍有差异,这时就应当使用抽象基类而不是接口,对比着上面的例子,原因也有三条:interface ISwim void Swim(); public class Pers

11、on : ISwim public void Swim() /Swimming in persons style. public class Frog : ISwim public void Swim() /Swimming in frogs style. public class Fish : ISwim public void Swim() /Swimming in fishs style. 1. 共性大于个性 2. 共性相同的个体间必然具有相同的属性与行为 3. 相同行为的实现方式具有一定区别abstract public class Fish abstract public void

12、Swim(); public class 鲫鱼 : Fish public override void Swim() /Swim like a 鲫鱼 public class 鲤鱼 : Fish public override void Swim() /Swim like a 鲤鱼 public class 金鱼 : Fish public override void Swim() /Swim like a 金鱼 观 察在使用接口或是使用抽象基类的几条理由中,第三条理由其实是一样的,它所描述的是面向对象中多态的概念,即通过覆盖父类的方法来实现,在运行时根据传递 的对象引用,来调用相应的方法。第

13、二条理由开始产生分歧,接口更加强调了继承对象间具有相同的行为,而抽象类同时还强调了继承对象间具有相同的属性。而真 正将接口与抽象基类区分开的则是理由一,归纳如下: 当在差异较大的对象间寻求功能上的共性时,使用接口。 当在共性较多的对象间寻求功能上的差异时,使用抽象基类。 通过相同与不同的比较,我们只能说接口和抽象类,各有所长,但无优略。在实际的编程实践中,我们要视具体情况来酌情量才,但是以下的经验和积累,或许能给 大家一些启示,除了我的一些积累之外,很多都来源于经典,我相信经得起考验。所以在规则与场合中,我们学习这些经典,最重要的是学以致用,当然我将以一家 之言博大家之笑,看官请继续。 规则与

14、场合1.请记住,面向对象思想的一个最重要的原则就是:面向接口编程。2.借助接口和抽象类,23个设计模式中的很多思想被巧妙的实现了,我认为其精髓简单说来就是:面向抽象编程。 3.抽象类应主要用于关系密切的对象,而接口最适合为不相关的类提供通用功能。 4.接口着重于CAN-DO关系类型,而抽象类则偏重于IS-A式的关系; 5.接口多定义对象的行为;抽象类多定义对象的属性; 6.接口定义可以使用public、protected、internal 和private修饰符,但是几乎所有的接口都定义为public,原因就不必多说了。 7.“接口不变”,是应该考虑的重要因素。所以,在由接口增加扩展时,应该增

15、加新的接口,而不能更改现有接口。 8.尽量将接口设计成功能单一的功能块,以.NET Framework为例,IDisposable、IDisposable、IComparable、IEquatable、IEnumerable等都只包含一个公共方法。 9.接口名称前面的大写字母“I”是一个约定,正如字段名以下划线开头一样,请坚持这些原则。 10.在接口中,所有的方法都默认为public。 11. 如果预计会出现版本问题,可以创建“抽象类”。例如,创建了狗(Dog)、鸡(Chicken)和鸭(Duck),那么应该考虑抽象出动物 (Animal)来应对以后可能出现风马牛的事情。而向接口中添加新成员则

16、会强制要求修改所有派生类,并重新编译,所以版本式的问题最好以抽象类来实 现。 12.从抽象类派生的非抽象类必须包括继承的所有抽象方法和抽象访问器的实实现。 13.对抽象类不能使用new关键字,也不能被密封,原因是抽象类不能被实例化。 14.在抽象方法声明中不能使用 static 或 virtual 修饰符。抽象类和接口有很多相似之处:接口表示调用者和设计者的一种约定,在多人合作开发同一个项目时,事先定义好相互调用的接口可以大大提高开 发的效率。接口是用类来实现的,实现接口的类必须严格按照接口的声明来实现接口提供的所有功能。有了接口,就可以在不影响现有接口声明的情况下,修改接口 的内部实现,从而

17、使兼容性问题最小化。当其他设计者调用了接口后,就不能再随意更改接口的定义,否则项目开发者事先的约定就失去了意义。但是可以在类中修改相应的代码,完成需要改动的内容。抽象类是指这个类是不完全可用的,只能作为其它类的基类。抽象类和其它非抽象类的最大区别之处在于:抽象类不能被实例化。1) 抽象类和接口都不能被实例化2)接口是完全抽象的成员集合;抽象类可以完全实现,也可以部分实现或者根本不实现,从而封装继承类的通用功能3) 抽象类只能作为基类使用,接口可以从其它基接口继承4)接口成员默认访问方式是public,接口成员定义不能包含任何访问修饰符;抽象类则不然5) 接口中不能声明任何种类的静态成员,抽象类

18、则可以6) 接口成员必须只能是方法、属性、索引器和事件,且不提供实现;抽象类还可以声明字段以及实现的方法和属性等7) 抽象方法只能在抽象类中声明使用接口或抽象类为组件提供多态性主要考虑一下几个方面:1. 如果预计要创建组件的多个版本,则创建抽象类。抽象类提供简单易行的方法来控制组件版本。通过更新基类,使所有继承类都自动更新。另一方面,为了保护为使 用接口而编写的现有系统,要求接口一旦创建就不能更改。如果需要接口的新版本,必须创建一个全新的接口。2. 如果创建的功能将在大范围的完全不同的对象间使用,则使用接口。抽象类应主要用于关系密切的对象,而接口最适合为不相关的类提供通用功能。3. 如果要设计

19、小而简炼的功能块,则使用接口;如果设计大的功能单元,则使用抽象类。设计优良的接口往往很小且相互独立,减少发生性能问题的可能。4. 如果要在组件的所有实现间传递通用的已实现功能,则使用抽象类。抽象类允许部分实现类,而接口不包含任何成员的实现。什么时候用抽象类,什么时候用接口 “接口是完全抽象的成员集合,它的成员都无法在接口定义时实现,我们可以将它看作是为操作定义合同,接口的实现完全留给开发者去做。它们之间的区别,如果认真分析,还是有不少的:在JAVA中,类只能是从一个基类继承,所以如果要使用抽象类为一组类提供多态性,这些类必须都是从那个类继承的;接口就不一样了,它不但可以用一个类或结构实现多个接

20、口,一个接口还可以有多个实现。” 抽象类是一种不能实例化而必须从中继承的类。抽象类可以完全实现,但更常见的是部分实现或者根本不实现,从而封装继承类的通用功能,它可以提供已实现的成员,因此,可以用抽象类确保特定数量的相同功能,但不能用接口这样做。 “也就是说,它们在提供多态性的问题上是有差别的?”我好象听懂了点什么。 “如果预计要创建组件的多个版本,我们应该创建抽象类。这是因为,抽象类提供简单易行的方法来控制组件版本。通过更新基类,所有继承类都随更改自动更新。这是好处,当然也是问题.另一方面,接口一旦创建就不能更改。如果需要接口的新版本,必须创建一个全新的接口。所以,如果创建的功能将在大范围的全

21、异对象间使用,则使用接口。”-:“能不能这样说,抽象类主要用于关系密切的对象,而接口最适合为不相关的类提供通用功能。” 我上午跟你说,要创建控件,首先就是要对一些接口进行实现以让系统能够识别(详见前文接口)。而各个控件之间的联系其实关联性并不大。所以,它们的基础大都是接口。但是,我们要注意一点,在组件设计时,如果要在组件的所有实现间提供通用的已实现功能,则使用抽象类。这是因为我们刚才说过的原因,抽象类允许部分实现类,而接口不包含任何成员的实现。” “唔,明白了,它们之间的区别有点明白了。”我默默地点了点头。 “另外,有个通用的设计思想,如果要设计小而简练的功能块,则使用接口。如果要设计大的功能

22、单元,则使用抽象类。” “看来设计的问题还是蛮大的,一般来说,怎么设计接口呢?”我接着问。 “为什么你所看到的编程书籍也好,程序例程也好,极少有对接口的描述,而对类实现继承的例子比比皆是?这就从一个侧面给我们提了一个醒,如果使用适当,接口可以成为很有用的工具。但如果使用不当,它们会变得非常棘手,甚至妨碍有效的编程。接口的设计与使用其实是一项高明的艺术。” ,“通过接口与实现的方式,我们可以将同一类型的程序运用在不同的对象上面,而且不必修改原有类,相对子程序必须通过修改源程序代码才能够达到重用的目的,接口与实现不仅是伟大的进步,也是境界极高的程序设计艺术。” “但是,最大的问题还是集中在接口设计

23、上。接口一旦被定义和接受,就必须保持不变,以保护为使用该接口而编写的应用程序。接口发布后,就不能对其进行更改。这是我们进行组件设计的一个重要原则,叫做接口不变性。” “我已经反反复复强调过,创建一个接口就是在创建一个定义,接口定义发布后则永远不能更改。接口不变性,就是为了保护为使用接口而编写的现有系统。当接口设计与需求有所出入,确认需要大幅度变更时,我们应该创建新的接口。一般命名方式是,新接口可以通过在原来的接口名称后追加一个数字2来命名,以显示出它与现有接口的关系。然后通过接口继承来创建新接口。” “可是,如果需求分析得不好,岂不是会出现一大堆的派生接口了?”我不免有点顾虑。 “这是肯定的,

24、而且过于频繁地生成新接口,会因未使用的接口实现而使组件变得很庞大。有经验的设计师,在充分分析需求后,设计出的接口往往很小且相互独立,减少了性能问题发生的可能。” “这种分解能力倒真的是艺术呀!”我不禁为之叹服。 “当然,一般来说,我们会把确定哪些属性和方法属于接口的设计过程称为接口分解。基本准则是,应在一个接口中将紧密相关的几个功能聚合为一组。功能太多会使接口不便于运行,而过于细分功能将导致额外的系统开销并降低使用的简易性。掌握分解的这个度的能力是需要不断的在技术上进行磨炼,以及在对每个项目深入分析与理解的基础上才能得到的。” 接口与类实现继承相比,好处有什么?”:“我试着说一下吧,总体而言,

25、接口是一种非常有效的编程方法,它让对象的定义与实现分离,从而可以在不破坏现有应用程序的情况下使对象得以完善与进化。接口消除了实现继承的一个大问题,就是在对设计实施后再对其进行更改时很可能对代码产生破坏。即使实现继承允许类从基类继承实现,在类首次发布时仍然会使我们不得不为设计做很多的抉择。如果原有的设想不正确,并非总可以在以后的版本中对代码进行安全的更改。比如,我们定义了一个基类的方法,它需要一个 Integer 参数,而后来又确定该参数应该为 Long 数据类型。我们无法安全更改原始类,因为为从原始类派生的类所设计的应用程序可能无法进行正确编译。这一问题会扩大化,因为单个基类会影响几百个子类。

26、” “那用重载原始类并采用一个Long类型的参数,不就能解决这个问题了吗?”大李提了个问题。 “这个么?”我想了一下,“可是,这样不一定能达到满意的效果,因为一个派生类可能需要对采用整数的方法进行重写,如果取 Long 数据类型的方法不能被重写,该派生类可能无法正常运行。” “那用接口怎么做?”大李不依不挠地继续问。 “办法就是发布接受新数据类型的更新接口。”我一下子就回答出来了。 “看来你已经掌握了接口操作的基本环节了。”大李的评语真让我高兴。“我再帮你总结一下,使用接口继承而不用类继承的主要原因有:在应用程序要求很多可能不相关的对象类型以提供某种功能的情况下,用接口适用性会更强;接口比基类更灵活,因为可以定义单个实现来实现多个接口;在无需从基类继承实现的情况下,接口更好;在无法使用类继承的情况下接口是很有用的。例如,结构无法从类继承,但它们可以实现接口。”

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

当前位置:首页 > 科普知识


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