1.接口的声明
接口的声明不能包含:数据成员,静态变量;只能包含如下类型的静态成员函数的声明:方法,属性,事件,索引器。声明中不能包含任何实现的代码,而在每个成员成名的主体后,必须使用分号。
接口声明可以有任何的修饰符public、protect、internl或private。
接口的成员是隐式的public,不允许任何访问修饰符,包括public。
1 Public Interface IMyInterface 2 { 3 //接口成员是隐式的public,并且只有声明 4 int Method1(int nVar1,int nVar2) ; 5 }
2.接口的实现
只有类和结构体才能实现接口,并且必须在基类列表中包括接口名称;使用接口的类或结构需要为接口的每一个成员提供实现。
1 Class MyClass:IMyInterface 2 { 3 //在进行隐式的实现接口成员的时候,访问修饰符要设为public 4 public int Method(int a,int b) 5 { 6 Console.WriteLine("{0}",a+b); 7 return a+b; 8 } 9 }
如果一个类即继承了基类,又实现了接口,那么在这个类的基类列表中的基类名称必须放在所有的接口的前面。并且一个类只能有一个基类,列出的其他类型必须都是接口名。
接口不仅仅是类或结构要实现的成员列表,它是一个引用类型,我们不能直接通过类对象的成员访问接口,然而我们可以通过把类对象引用强制转换为接口类型来获取指向接口的引用。这样我们就可以使用点号来调用接口的方法了。这里转换推荐用as进行转换。
1 Static void Main(string[] args) 2 { 3 int a = 5; 4 int b = 8; 5 MyClass mc = new MyClass(); 6 //调用类对象的实现方法 7 mc.Method(a,b); 8 //将类型转化为接口类型 9 IMyInterface mif = mc as IMyInterface; 10 mif.Method(a,b); 11 }
输出结果:13
13
利用as进行强制转换的好处:如果类实现了接口就会返回接口的引用(平安无事)如果类没有实现接口就会抛出异常,方便及时的发现错误。
3.实现多个接口
类或结构可以实现任意数量的接口。
所有实现的接口必须列在基类列表中且以逗号分隔。
如果一个类实现的两个接口当中有重复的成员(具有相同的签名和相同的返回类型),那么在该类实现接口成员的时候,实现一次就可以满足所有包含重复成员的接口。
1 interface interface1 { void Method(int a ,int b);} 2 interface interface2 { void Method(int a, int b);} 3 //实现多个接口用逗号相隔 4 public class MyClass : interface1, interface2 5 { 6 /* 7 * 如果两个接口成员函数的返回类型和参数一致, 8 * 那么进行一次实现就可以了 9 */ 10 public void Method(int a, int b) 11 { 12 Console.WriteLine("{0}", a + b); 13 } 14 }
如果想刻意的分离这两个接口的接口成员,就需要创建显式的接口成员成员实现。格式:接口名称+点分隔符+接口的成员函数。注意:在显示的调用接口成员的时候,已经默认为public,不能再添加访问修饰符了。
1 interface interface1 { void Method(int a ,int b);} 2 interface interface2 { void Method(int a, int b);} 3 //实现多个接口用逗号相隔 4 public class MyClass : interface1, interface2 5 { 6 //显示的实现interface1的接口成员 7 //已经默认为public,不能添加访问修饰符了 8 void interface1.Method(int a, int b) 9 { 10 Console.WriteLine("{0}", a + b); 11 } 12 void interface2.Method(int a, int b) 13 { 14 Console.WriteLine("{0}", a + b); 15 } 16 }
但是这样就只有显式接口成员的实现,而没有类级别的实现,所以在实例化该类的对象后,是无法点出该方法的。如果有显式接口成员实现,类级别的实现是允许的,但是不是必须的。并且显式接口成员实现智能通过指向接口的引用来访问,即使是类当中的成员函数来对接口成员进行访问。
如果一个类实现了接口,那么它的子类也会继承其基类实现的接口成员,无需再次实现。
4.接口的继承
要指定某个接口继承其他接口,应在接口声明中把接口以逗号分隔的列表形式放在接口名称之后。和类的继承格式相同。但是又与类不同,一个接口可以继承任意多个接口,可以进行多重继承。子接口除了包含自己声明的接口之外还包括所有父接口的所有接口成员。
5.代码Demo
1 namespace ConsoleApplication2 2 { 3 interface ILoveWorld { void SayHello();} 4 class Creature{} 5 6 //基类和接口同时实现的时候,基类要放在最前面 7 class Person : Creature,ILoveWorld 8 { 9 //隐式的声明接口,既可以被类的对象访问,又可以转换为接口引用对象访问 10 void SayHello() 11 { 12 Console.WriteLine("Hello World!"); 13 } 14 //显式的声明接口成员,只能转换为接口引用对象来访问 15 void ILoveWorld.SayHello() 16 { 17 Console.WriteLine("Hello World!"); 18 } 19 } 20 class Cat : Creature, ILoveWorld 21 { 22 //相对于显式的接口实现方式。类级别的接口实现不是必须的。 23 void ILoveWorld.SayHello() 24 { 25 Console.WriteLine("MiaoMiaoMiao"); 26 } 27 } 28 class Dog : Creature, ILoveWorld 29 { 30 //在显式调用接口成员的时候不能用public 31 void ILoveWorld.SayHello() 32 { 33 Console.WriteLine("WangWangWang"); 34 } 35 } 36 class Program 37 { 38 static void Main(string[] args) 39 { 40 //声明一个Creature的数组 41 Creature[] pCreatureArray = new Creature[3]; 42 //这里用到了上次学的面向对象的IS-A的关系 43 pCreatureArray[0] = new Person(); 44 pCreatureArray[1] = new Cat(); 45 pCreatureArray[2] = new Dog(); 46 foreach (var creature in pCreatureArray) 47 { 48 //利用as进行转换 49 ILoveWorld b = creature as ILoveWorld; 50 b.SayHello(); 51 } 52 Console.ReadKey(); 53 } 54 } 55 }
运行结果: