本文在文字说明的时候将不会举例,在文章写完后,在列出整个例子
二、接口:(interface)
接口是引用类型的,类似于类
接口有如下特性:接口除了可以包含方法之外,还可以包含属性、索引器、事件,而且这些成员都被定义为公有的。除此之外,不能包含任何其他的成员,例如:常量、域、构造函数、析构函数、静态成员。一个类可以直接继承多个接口,但只能直接继承一个类(包括抽象类)。
使用C#接口应注意几个问题:
1、C#中的接口是独立于类来定义的。这与 C++模型是对立的,在 C++中接口实际上就是抽象基类。
2、接口和类都可以继承多个接口。
3、类可以继承一个基类,接口根本不能继承类。C#的简化接口模型有助于加快应用程序的开发。
4、一个接口定义一个只有抽象成员的引用类型。C#中一个接口实际所做的,仅仅只存在着方法标志,但根本就没有执行代码。这就暗示了不能实例化一个接口,只能实例化一个派生自该接口的对象。
5、接口可以定义方法、属性和索引。所以,对比一个类,接口的特殊性是:当定义一个类时,可以派生自多重接口,而你只能可以从仅有的一个类派生。
6、好的接口定义应该是具有专一功能性的,而不是多功能的,否则造成接口污染。如果一个类只是实现了这个接口的中一个功能,而不得不去实现接口中的其他方法,就叫接口污染。
7、如果抽象类实现接口,则可以把接口中方法映射到抽象类中作为抽象方法而不必实现,而在抽象类的子类中实现接口中方法.
三、接口和抽象类的相似之处有四点:
1、不能实例化,但可以声明它们的变量 ;
2、包含未实现的方法声明;
3、派生类必须实现未实现的方法,抽象类是抽象方法,接口则是所有成员(不仅是方法包括其他成员);
4、接着通过这些变量来使用这些类型的成员,但不能直接访问派生对象的其它成员。
四、抽象类和接口的区别:
1、派生类只能继承一个基类,即只能直接继承一个抽象类(但可以用一个继承链包含多个抽象类)。相反,类可以使用任意多个接口。
2、抽象类可以拥有抽象成员和非抽象成员。
抽象成员:没有代码体,且必须在派生类中执行,否则派生类本身必须也是抽象的。
非抽象成员:拥有代码体,也可以是虚拟的,这样就可以在派生类中重写。
3、接口成员必须都在使用接口的类上执行——它们没有代码体。
4、接口成员被定义为公共的,但抽象类的成员也可以是私有的、受保护的、内部的或受保护的内部成员(其中受保护的内部成员只能在应用程序的代码或派生类中访问)。此外,接口不能包含字段、构造函数、析构函数、静态成员或常量。
5、类是对对象的抽象,可以把抽象类理解为把类当作对象,抽象成的类叫做抽象类.而接口只是一个行为的规范或规定,微软的自定义接口总是后带able字段,证明其是表述一类类“我能做......”。抽象类更多的是定义在一系列紧密相关的类间,而接口大多数是关系疏松但都实现某一功能的类中.
一些专家看法:
dunai认为:抽象类是提取具体类的公因式,而接口是为了将一些不相关的类“杂凑”成一个共同的群体。至于他们在各个语言中的句法,语言细节并不是我关心的重点。
Artech认为:所代码共用和可扩展性考虑,尽量使用Abstract Class。当然接口在其他方面的优势,我认为也不可忽视。
shenfx认为:当在差异较大的对象间寻求功能上的共性时,使用接口;当在共性较多的对象间寻求功能上的差异时,使用抽象基类。
最后,有关C#接口和抽象类的学习,MSDN的建议:
如果预计要创建组件的多个版本,则创建抽象类。抽象类提供简单易行的方法来控制组件版本。通过更新基类,所有继承类都随更改自动更新。另一方面,接口一旦创建就不能更改。如果需要接口的新版本,必须创建一个全新的接口。
如果创建的功能将在大范围的全异对象间使用,则使用接口。抽象类应主要用于关系密切的对象,而接口最适合为不相关的类提供通用功能。
如果要设计小而简练的功能块,则使用接口。如果要设计大的功能单元,则使用抽象类。
如果要在组件的所有实现间提供通用的已实现功能,则使用抽象类。抽象类允许部分实现类,而接口不包含任何成员的实现。
网上的一个比喻:
1.飞机会飞,鸟会飞,他们都继承了同一个接口“飞”;但是F22属于飞机抽象类,鸽子属于鸟抽象类。
2. 就像铁门木门都是门(抽象类),你想要个门我给不了(不能实例化),但我可以给你个具体的铁门或木门(多态);而且只能是门,你不能说它是窗(单继承);一个门可以有锁(接口)也可以有门铃(多实现)。 门(抽象类)定义了你是什么,接口(锁)规定了你能做什么(一个接口最好只能做一件事,你不能要求锁也能发出声音吧(接口污染))。
例子:
1、新建一个控制台应用程序ClassTest,新建类Animals
public abstract class Animals { protected string _name; //声明抽象属性 public abstract string Name { get; } //声明抽象方法 public abstract void Show(); //实现虚方法 public virtual void MakeVoice() { Console.WriteLine("All animals can make voice."); } //实现一般的方法 public void Sleep() { Console.WriteLine("All the animals need to sleep."); } }
2、新建一个接口IAction
public interface IAction { void Move(); }
3、新建一个Duck类:
public class Duck : Animals, IAction { public Duck(string name) { _name = name; } //重写抽象属性 public override string Name { get { return _name; } } //重写抽象方法,抽象方法必须重写 public override void Show() { Console.WriteLine(_name + " is showing for you!"); } //重写虚方法 public override void MakeVoice() { Console.WriteLine("I am a duck,ga....ga...."); } //实现接口方法 public void Move() { Console.WriteLine("Duck also can swim."); } }
4、新建一个Dog类:
public class Dog : Animals, IAction { public Dog(string name) { _name = name; }
//重写抽象属性 public override string Name { get { return _name; } }
//重写抽象方法,抽象方法必须重写 public override void Show() { Console.WriteLine(_name + " is showing for you!"); }
//实现接口方法 public void Move() { Console.WriteLine("Dog also can run."); } }
5、在Main函数中写代码:
static void Main(string[] args) { Animals duck=new Duck("Duck"); Console.WriteLine(duck.Name); duck.Sleep(); duck.Show(); duck.MakeVoice();//调用重写后的虚方法 Console.WriteLine(); Animals dog=new Dog("Dog"); Console.WriteLine(dog.Name); dog.Sleep(); dog.Show(); dog.MakeVoice();//直接调用基类虚方法 Console.WriteLine(); Dog dog1=new Dog("Dog1"); Console.WriteLine(dog1.Name); dog1.Show(); Console.WriteLine(); IAction dog2=new Dog("A big dog"); dog2.Move(); Console.WriteLine(); }
6、执行结果如下:
参考资料:
《C#语言参考》
《C#完全手册》
http://www.cnblogs.com/bear-study-hard/archive/2006/01/09/313673.html
http://blog.csdn.net/gz2008gz/article/details/4365971