什么是网站开发框架,网站建站家,长沙网站建设+个人,公司建设网站的申请信用卡本文将介绍以下内容#xff1a;
• 面向对象思想#xff1a;多态
• 接口
• 抽象类 1. 引言
在我之前的一篇post《抽象类和接口的谁是谁非》中#xff0c;和同事管伟的讨论#xff0c;得到很多朋友的关注#xff0c;因为是不成体系的论道#xff0c;所以给大家了解造… 本文将介绍以下内容
• 面向对象思想多态
• 接口
• 抽象类 1. 引言
在我之前的一篇post《抽象类和接口的谁是谁非》中和同事管伟的讨论得到很多朋友的关注因为是不成体系的论道所以给大家了解造成不便同时关于这个主题的系统性理论我认为也有必要做以总结因此才有了本篇的新鲜出炉。同时我将把上贴中的问题顺便也在此做以交代。
2. 概念引入
什么是接口
接口是包含一组虚方法的抽象类型其中每一种方法都有其名称、参数和返回值。接口方法不能包含任何实现CLR允许接口可以包含事件、属性、索引器、静态方法、静态字段、静态构造函数以及常数。但是注意C#中不能包含任何静态成员。一个类可以实现多个接口当一个类继承某个接口时它不仅要实现该接口定义的所有方法还要实现该接口从其他接口中继承的所有方法。
定义方法为 public interface System.IComparable { int CompareTo(object o); } public class TestCls: IComparable { public TestCls() { } private int _value; public int Value { get { return _value; } set { _value value; } } public int CompareTo(object o) { //使用as模式进行转型判断 TestCls aCls o as TestCls; if (aCls ! null) { //实现抽象方法 return _value.CompareTo(aCls._value); } } }什么是抽象类
抽象类提供多个派生类共享基类的公共定义它既可以提供抽象方法也可以提供非抽象方法。抽象类不能实例化必须通过继承由派生类实现其抽象方法因此对抽象类不能使用new关键字也不能被密封。如果派生类没有实现所有的抽象方法则该派生类也必须声明为抽象类。另外实现抽象方法由overriding方法来实现。
定义方法为
/// summary/// 定义抽象类/// /summaryabstract public class Animal { //定义静态字段 protected int _id; //定义属性 public abstract int Id { get; set; } //定义方法 public abstract void Eat(); //定义索引器 public string this[int i] { get; set; } } /// summary/// 实现抽象类/// /summarypublic class Dog: Animal { public override int Id { get {return _id;} set {_id value;} } public override void Eat() { Console.Write(Dog Eats.) } } 3. 相同点和不同点
3.1 相同点
都不能被直接实例化都可以通过继承实现其抽象方法。都是面向抽象编程的技术基础实现了诸多的设计模式。
3.2 不同点
接口支持多继承抽象类不能实现多继承。接口只能定义抽象规则抽象类既可以定义规则还可能提供已实现的成员。接口是一组行为规范抽象类是一个不完全的类着重族的概念。接口可以用于支持回调抽象类不能实现回调因为继承不支持。接口只包含方法、属性、索引器、事件的签名但不能定义字段和包含实现的方法抽象类可以定义字段、属性、包含有实现的方法。 接口可以作用于值类型和引用类型抽象类只能作用于引用类型。例如Struct就可以继承接口而不能继承类。通过相同与不同的比较我们只能说接口和抽象类各有所长但无优略。在实际的编程实践中我们要视具体情况来酌情量才但是以下的经验和积累或许能给大家一些启示除了我的一些积累之外很多都来源于经典我相信经得起考验。所以在规则与场合中我们学习这些经典最重要的是学以致用当然我将以一家之言博大家之笑看官请继续。
3.3 规则与场合
请记住面向对象思想的一个最重要的原则就是面向接口编程。借助接口和抽象类23个设计模式中的很多思想被巧妙的实现了我认为其精髓简单说来就是面向抽象编程。抽象类应主要用于关系密切的对象而接口最适合为不相关的类提供通用功能。接口着重于CAN-DO关系类型而抽象类则偏重于IS-A式的关系接口多定义对象的行为抽象类多定义对象的属性 接口定义可以使用public、protected、internal 和private修饰符但是几乎所有的接口都定义为public原因就不必多说了。“接口不变”是应该考虑的重要因素。所以在由接口增加扩展时应该增加新的接口而不能更改现有接口。尽量将接口设计成功能单一的功能块以.NET Framework为例IDisposable、IDisposable、IComparable、IEquatable、IEnumerable等都只包含一个公共方法。接口名称前面的大写字母“I”是一个约定正如字段名以下划线开头一样请坚持这些原则。在接口中所有的方法都默认为public。 如果预计会出现版本问题可以创建“抽象类”。例如创建了狗Dog、鸡Chicken和鸭Duck那么应该考虑抽象出动物Animal来应对以后可能出现风马牛的事情。而向接口中添加新成员则会强制要求修改所有派生类并重新编译所以版本式的问题最好以抽象类来实现。从抽象类派生的非抽象类必须包括继承的所有抽象方法和抽象访问器的实实现。对抽象类不能使用new关键字也不能被密封原因是抽象类不能被实例化。在抽象方法声明中不能使用 static 或 virtual 修饰符。
以上的规则我就厚颜无耻的暂定为T14条吧写的这么累就当一时的奖赏吧。大家也可以互通有无我将及时修订。
4. 经典示例
4.1 绝对经典
.NET Framework是学习的最好资源有意识的研究FCL是每个.NET程序员的必修课关于接口和抽象类在FCL中的使用我有以下的建议
FCL对集合类使用了基于接口的设计所以请关注System.Collections中关于接口的设计实现FCL对数据流相关类使用了基于抽象类的设计所以请关注System.IO.Stream类的抽象类设计机制。
4.2 别样小菜
下面的实例因为是我的理解因此给经典打上“相对”的记号至于什么时候晋升为“绝对”就看我在.NET追求的路上是否能够一如既往的如此执着因此我将把相对重构到绝对为止呵呵。 本示例没有阐述抽象类和接口在设计模式中的应用因为那将是另一篇有讨论价值的文本本文着眼与概念和原则的把握但是真正的应用来自于具体的需求规范。
设计结构如图所示 1. 定义抽象类 public abstract class Animal { protected string _name; //声明抽象属性 public abstract string Name { get; } //声明抽象方法 public abstract void Show(); //实现一般方法 public void MakeVoice() { Console.WriteLine(All animals can make voice!); } }2. 定义接口 public interface IAction { //定义公共方法标签 void Move(); }3. 实现抽象类和接口 public class Duck : Animal, IAction { public Duck(string name) { _name name; } //重载抽象方法 public override void Show() { Console.WriteLine(_name is showing for you.); } //重载抽象属性 public override string Name { get { return _name;} } //实现接口方法 public void Move() { Console.WriteLine(Duck also can swim.); } } public class Dog : Animal, IAction { public Dog(string name) { _name name; } public override void Show() { Console.WriteLine(_name is showing for you.); } public override string Name { get { return _name; } } public void Move() { Console.WriteLine(_name also can run.); } }4. 客户端实现 public class TestAnmial { public static void Main(string [] args) { Animal duck new Duck(Duck); duck.MakeVoice(); duck.Show(); Animal dog new Dog(Dog); dog.MakeVoice(); dog.Show(); IAction dogAction new Dog(A big dog); dogAction.Move(); } }5. 他山之石
正所谓真理是大家看出来的所以将园子里有创新性的观点潜列于此一是感谢大家的共享二是完善一家之言的不足希望能够将领域形成知识受用于我受用于众。
dunai认为抽象类是提取具体类的公因式而接口是为了将一些不相关的类“杂凑”成一个共同的群体。至于他们在各个语言中的句法语言细节并不是我关心的重点。桦山涧的收藏也很不错。Artech认为所代码共用和可扩展性考虑尽量使用Abstract Class。当然接口在其他方面的优势我认为也不可忽视。shenfx认为当在差异较大的对象间寻求功能上的共性时使用接口当在共性较多的对象间寻求功能上的差异时使用抽象基类。最后MSDN的建议是
如果预计要创建组件的多个版本则创建抽象类。抽象类提供简单易行的方法来控制组件版本。通过更新基类所有继承类都随更改自动更新。另一方面接口一旦创建就不能更改。如果需要接口的新版本必须创建一个全新的接口。如果创建的功能将在大范围的全异对象间使用则使用接口。抽象类应主要用于关系密切的对象而接口最适合为不相关的类提供通用功能。如果要设计小而简练的功能块则使用接口。如果要设计大的功能单元则使用抽象类。如果要在组件的所有实现间提供通用的已实现功能则使用抽象类。抽象类允许部分实现类而接口不包含任何成员的实现。
6. 结论
接口和抽象类是论坛上、课堂间讨论最多的话题之一之所以将这个老话题拿出来再议是因为从我的体会来说深刻的理解这两个面向对象的基本内容对于盘活面向对象的抽象化编程思想至关重要。本文基本概况了接口和抽象类的概念、异同和使用规则从学习的观点来看我认为这些总结已经足以表达其核心。但是对于面向对象和软件设计的深入理解还是建立在不断实践的基础上Scott说自己每天坚持一个小时用来写Demo那么我们是不是更应该勤于键盘呢。对于接口和抽象类请多用而知其然多想而知其奥吧。
参考文献
USAJeffrey Richter, Applied Microsoft .NET Framework Programming