C#接口和抽象类的总结
来源:互联网 发布:linux中samba干嘛用 编辑:程序博客网 时间:2024/05/20 13:38
一、接口的简单实现
接口更好地实现了多态,体现了约定和实现相分离的原则。通过面向接口编程,可以降低代码间的耦合性,提高代码的可扩展性和可维护性。在面向对象编程中,提倡面向接口编程,而不是面向实现编程。面向接口编程意味着,开发系统时,主体架构使用接口,接口构成系统的骨架,这样就可以通过更换实现接口的类来实现更换系统。一个类实现的某个接口,就表示这个类具有了某种能力,这个能力具体体现在实现接口的方法上。
如下代码,有一个Duck父类,它有三个子类,RealDuck、WoodDuck、RubberDuck。其中RealDuck和RubberDuck会叫,只是叫声不一样,WoodDuck不会叫。有一个鸭子叫的接口IBark。
/// <summary> /// 鸭类 /// </summary> public class Duck { public void Swin() //游泳方法 { Console.WriteLine("鸭子在水中游..."); } } //鸭子叫的接口 public interface IBark { void Bark(); } /// <summary> /// 真实的鸭子 /// </summary> public class RealDuck : Duck, IBark { public void Bark() { Console.WriteLine("嘎嘎叫..."); } } /// <summary> /// 橡皮鸭 /// </summary> public class RubberDuck : Duck, IBark { public void Bark() { Console.WriteLine("唧唧叫..."); } } /// <summary> /// 木头鸭 /// </summary> public class WoodDuck : Duck { }在Main()方法中,当我们想要让鸭子叫时,不能用父类变量指向会叫的鸭子对象,因为这样会让这个变量无法调用子类鸭子叫的方法,而是应该用接口来声明这个变量。代码如下:
static void Main(string[] args) { //Duck duck = new RealDuck(); IBark bark = new RealDuck(); bark.Bark(); Console.ReadKey(); }这样在控制台上显示的结果是“嘎嘎叫...”。
二、显式实现接口
先看如下示例代码,一个具有飞行功能的接口IFlyable,一个可以飞行的超人接口ISuperman,这两个接口里面有一个同名的飞行方法Fly,另外有一个学生类同时继承了这两个接口,并且实现了接口所具有的Fly()方法,一个是直接实现,一个是显式实现。
//具有飞行功能的接口 public interface IFlyable { void Fly(); } //具有飞行功能的超人接口 public interface ISuperman { void Fly(); } public class Student : IFlyable,ISuperman { public void Fly() { Console.WriteLine("IFlyable接口中的Fly方法"); } void ISuperman.Fly() { Console.WriteLine("ISuperman接口中的Fly方法(显示实现的方法)"); } }在Main方法中,我们让三个不同类型的变量分别指向一个学生对象,如下:
static void Main(string[] args) { IFlyable fly = new Student(); //飞行类 fly.Fly(); ISuperman man = new Student(); //超人类 man.Fly(); Student stu = new Student(); //学生类 stu.Fly(); Console.ReadKey(); }运行程序,结果如图所示:
从上面可以看出,显式实现的Fly方法的对象只有用实现该显式方法的接口来声明,我们才可以调用这个显式方法。在上面的代码中,你会发现,显式实现的方法前面没有访问修饰符,也就是默认为private,而直接实现的方法的访问修饰符是public。如果在显式实现的方法前面加一个public访问修饰符,那么程序就会报错,如图所示:
错误信息提示我们:修饰符public对该项无效。这也告诉我们,显式实现接口的方法必须为private。既然这个方法是私有的,那在外界就不能访问了,那我们用ISuperman类型的变量指向的Student对象为什么又可以访问到呢?因为这个对象访问的是ISuperman接口中的Fly方法,而所有接口中的方法都默认必须为public,并且继承这个接口的Student类已经显式的实现了这个Fly方法,所以可以访问到。显式实现接口的目的,就是为了解决方法重名的问题。
假如我们把Student类中直接实现的IFlyable接口的方法删掉,然后让这个接口也显式实现其方法,如下所示:
public class Student : IFlyable,ISuperman { //public void Fly() //{ // Console.WriteLine("IFlyable接口中的Fly方法"); //} void ISuperman.Fly() //显式实现ISuperman接口的方法 { Console.WriteLine("ISuperman接口中的Fly方法(显示实现的方法)"); } void IFlyable.Fly() //显式实现IFlyable接口的方法 { throw new NotImplementedException(); } }那么,在Main方法中,我们会发现程序报错,如图:
我们会发现,用Student类声明的对象无法访问到Fly这个方法,因为这个方法是私有的(private),外界声明的Student类型的对象无法访问。所以,我们可以得出结论,显式实现的方法必须要由实现显式方法的接口声明的对象调用。
三、接口特点的总结:
1.接口是一种规范,是为了更好的实现多态。
2.接口不能被实例化。
3.接口中的成员不能加访问修饰符。因为接口中的成员的访问修饰符默认就为public,不能修改。
4.接口中的成员不能有任何实现(也就是光说不做,只是定义了一组未实现的成员)。
5.接口中只能有方法、属性、索引器、事件,不能有字段。
6.接口与接口之间可以继承,并且可以多继承。
7.实现接口的子类必须实现该接口的全部成员。
8.一个类可以同时继承一个类并实现多个接口,如果一个子类同时继承了父类A,并且实现了接口IA,那么语法上A必须写在IA的前面,因为类是单继承的。
9.当一个抽象类实现接口的时候,如果不想把接口中的成员实现,可以把该成员实现为abstract。
10.显式实现接口,只能通过接口变量来调用,因为显式实现接口后,成员必须为private(上面已有示例)。
四、使用接口的建议:
面向抽象编程,我们提倡使用抽象(父类、抽象类、接口)而不使用具体,我们在编程时:
1.在定义方法返回值、参数、声明变量的时候能使用抽象就不要用具体。这个顺序一般为:接口→抽象类→父类→具体类。
2.能使用接口就不用抽象类,能用抽象类就不使用父类,能用父类就不使用子类。
3.避免定义体积庞大的接口和多功能接口,这样会造成接口污染。只需要把相关联的一组成员定义到一个接口中,尽量在接口中少定义成员,这就是单一职责原则。
4.我们一般应定义多个职责单一的接口来组合使用。
五、抽象类的特点
1.不能被实例化,需要被继承,这是为了实现多态。
2.子类必须重写父类所有的抽象成员,除非子类也是一个抽象类。
3.抽象成员在父类中不能的任何实现。
4.抽象类中可以有实例成员。
5.抽象成员的访问修饰符不能是private。
6.抽象成员只能写在抽象类中。
六、抽象类和接口的区别
1.抽象类适用于同一系列(类型),并且有需要继承的成员。
2.接口适用于不同系列的类具有相同的动作(行为、动作、方法)。
3.对于不是相同的系列,但具有相同的行为时,就应该要使用接口。
4.接口解决了类不能多继承的问题。
- C#接口和抽象类的总结
- C#抽象类和接口总结
- c#接口和抽象类的区别
- C#抽象类和接口的比较
- C#接口和抽象类的特点
- C#抽象类和接口的区别
- c#接口和抽象类的区别
- c#接口和抽象类的区别
- c#接口和抽象类的区别
- c#接口和抽象类的区别
- C#抽象类和接口的区别
- C#抽象类和接口的区别
- c#接口和抽象类的区别
- c#接口和抽象类的区别
- c#接口和抽象类的区别
- c#接口和抽象类的区别
- C#抽象类和接口的区别
- c#接口和抽象类的区别
- hdu 4473 Exam
- handler使用
- Spring AOP中pointcut expression表达式解析
- XML、JSON、PB(protocol buffer)的比较
- HDU4454(几何+三分)
- C#接口和抽象类的总结
- 网络传输过程中TCP/IP协议详解
- C++虚析构函数的作用
- Python的编译后文件介绍
- 面试中常考的现场写程序题目
- javacripts eval 慎用
- Linux下修改root密码以及找回密码的方法
- 802.11数据帧
- paip.提升用户体验---控件透明的设置