3. 用接口来实现多态
接口是一种规范,也是一种能力,当一个类要表现出某种能力的时候,一般都用接口来实现。
声明接口的方式: 接口的名称一般以 I 开头,以able结尾。因为以able结尾的单词代表某种能力。
[public] interface I .. able
{ 成员; }
接口的特点:
1)、接口不能被实例化;也就是说,接口不能new(不能创建对象)
2)、接口中的成员不能加“访问修饰符”,接口中的成员访问修饰符默认为public,不能修改。
3)、接口中的成员不能有任何实现(“光说不做”,只定义了一组未实现的成员,这点和抽象类相同)
4)、接口只能包含方法、属性、索引器、事件(后三者本质都为方法),不能有字段和构造函数。
5)、接口不能去继承一个类,而类可以继承接口(接口只能继承于接口,可以继承多个接口;而类既可以继承接口,也可以继承类)
6)、一个类可以同时继承一个类并实现多个接口,如果一个子类同时继承了父类A,并实现了接口IA,语法上A必须写在IA前面。 class MyClass : A , IA {} 因为类是单继承的。
class MyClass : A , IA , IB , IC {}
7)、只要一个类继承了接口,这个类就必须实现接口中的所有成员。
8)、子类实现接口的方法时,不需要任何关键字,直接实现即可。
9)、接口存在的意义就是为了实现多态
8)、当一个抽象类实现接口的时候,需要子类去实现接口。如果抽象类不想实现接口,就必须将该成员标记为abstract,交给子类去实现。
9)、显示实现接口的目的:解决方法的重名问题。
什么时候显示的去实现接口:当继承的接口与类中的方法,参数、返回值一模一样的时候,要显示的实现接口。
class Program { static void Main(string[] args) { Person p = new Person(); //调用Person类的 Cooking() p.Cooking(); // I AM COOKING //声明接口类型去指向类的对象 ICookingable ic = new Person(); //调用接口的Cooking() ic.Cooking(); // 显示实现接口 Cooking Console.ReadKey(); } } public class Person : ICookingable { public void Cooking() { Console.WriteLine("I AM COOKING"); } //显示实现接口的目的是为了解决 方法重名的问题 //在外面访问这个方法的时候,本质上访问的是接口的方法所以可以不用加public void ICookingable.Cooking() { Console.WriteLine("显示实现接口 Cooking"); } private int _time; int ICookingable.Time { get { return _time; } set { _time = value; } } private int _age; //普通属性:有对应的私有字段 public int Age { get { return _age; } set { _age = value; } } } public interface ICookingable { //默认访问修饰符为 public,但不能加 public来修饰 void Cooking(); //接口里面可以包含属性,因为属性的本质是两个方法:get set //这里的属性被称为自动属性,因为这里没有与它对应的私有字段 int Time { get; set; } } public interface ITestable { void Test(); } //接口可以继承接口 public interface ITeaable : ITestable { void Ttea(); }
什么时候使用接口来实现多态?
几个类无共同的父类,但有一个或者若干个共同的能力。
真正的狮子会吼,石头狮子不会吼,机器狮子会吼
这里不能以真正的狮子作为父类,因为石头狮子是不会吼的;这三种狮子,都与一个能力有关,就是吼;只要写一个狮子吼的接口,让真正的狮子、机器狮子继承这个接口,石头狮子不继承这个接口就可以了。
static void Main(string[] args) { //真正的狮子会吼,石头狮子不会吼,机器狮子会吼 LionBark lb1 = new RealLion(); lb1.Bark(); LionBark lb2 = new MachineLion(); lb2.Bark(); Console.ReadKey(); } public interface LionBark { void Bark(); //狮子吼 } public class RealLion : LionBark { void LionBark.Bark() { Console.WriteLine("真正的狮子,吼"); } } //由于石头狮子不会吼,所以不需要继承狮子吼这个接口 public class Stonelion { public void Bark() { Console.WriteLine("我不会吼"); } } public class MachineLion : LionBark { void LionBark.Bark() { Console.WriteLine("机器做的狮子也会吼"); } } }