小天:接口主要是给类做父类的吗?它还能不能继承其它的接口呢?
老田:当然是可以的,不过接口继承接口会有一个问题。通过前面的介绍也知道了,接口本身是不会去实现任何方法的。它只是规定了要实现那些方法,以及要什么样的材料(参数),能够生产什么样的产品(返回值)。于是,接口继承接口的结果就是越往后的接口所带的成员就越多了。例如,下面代码,
interface I_2_A //声明第一个接口 { int A { get; set; } //声明一个属性 } interface I_2_B //声明第二个接口 { int Count(int i, int j); //声明一个方法 } interface I_2_C : I_2_A, I_2_B {//声明第三个接口又继承了前两个接口 } //什么都没有声明。但是他实际上是继承了前面两个接口的属性和方法。 public class I_2_L : I_2_C //声明一个类,他继承了I_2_C这个接口 { int a; public int A { get { return a; } set { a = value; } } public int Count(int i, int j) { return i * j * a; } } class Program { //----------------------使用接口---------------------------------- static void Main(string[] args) { //接口第二个实例,I_2_A、I_2_B、I_2_C、I_2_L 的实例 //使用I_2_A,只有一个属性A I_2_A i2a = new I_2_L(); Console.WriteLine(i2a.A); //使用I_2_B,只有一个Count方法 I_2_B i2b = new I_2_L(); Console.WriteLine(i2b.Count(2,5)); //使用I_2_C,既有方法也有属性 I_2_C i2c = new I_2_L(); Console.WriteLine("i2c.A={0},i2c.Count(3,15)={1}", i2c.A, i2c.Count(3, 15));
Console.ReadLine(); } } |
上面一共申明了三个接口,分别是I_2_A中有一个A属性, I_2_B中有一个Count方法,接着就申明了I_2_C这个接口来继承前面两个接口。虽然这第三个接口中啥都没有,但是这一继承就有了一个属性和一个方法。于是I_2_L这个类来继承I_2_C这个接口,这便需要实现所有I_2_C这个接口所背负的责任。
打个很不恰当的比方,两个非常有大志的夫妻被困荒岛,他们不小心生了一个孩子,终于有一天,有人来就他们了。可惜这对夫妻已经很老了,无法离开这里。于是他们就将他们两的理想都加到孩子身上,希望得到实现。
另外,从上面看应该看出一点,接口可以多重继承,而多个接口之间则是用逗号分隔。语法如下:
类或接口 : 接口1,接口2,接口N //这是纯继承接口 类 : 类,接口1,接口2,接口N //类始终只能继承一个,但是可以混合继承 |
小天:既然可以多重继承,那么会不会出现成员重复的情况?比如接口1和接口2中某两个方法重复,这种情况下继承该怎么办?而使用的时候又怎么办?
老田:这个问题问得太好了,先看下面的实例:
public interface I_3_A { int Count { get; set; } int J(int j); } public interface I_3_B { void Count(int i); double J(double j); } public interface I_3_C : I_3_A, I_3_B { } //---------------------使用上面的接口-------------------- public class I_3_L { public void Sum(I_3_C thc) { thc.Count(); //错误,具有二义性 thc.Count = 1; //错误,具有二义性 thc.Count(1); //错误,具有二义性,其实相对来说,这个也可以说不具备二义性
((I_3_A)thc).Count = 1; //正确,最好是这样明确一点,也增加代码的易读性 ((I_3_B)thc).Count(1);
((I_3_A)thc).J(1); ((I_3_B)thc).J(1); thc.J(1.0); thc.J(1); } } |
从上面实例看得出来,外部对接口的访问,如果出现同名的参数或者方法,必须显示的指出他的父接口。特别是在不清楚具体情况的前提下,最好是做得保守一点。
小天:如果用一个抽象类来继承接口会是什么效果?
老田:一回事。上面不是说了,就算是抽象类来继承接口,那么也必须将接口的方法给实现了吗?就算自己不实现,那也必须让方法可以传递下去,被下面的派生来再来实现。如图4-32
图4-32
根据上面的类关系图写出代码,然后可以对照下面:
public interface I_4_A { int J(int j); } public interface I_4_B { int Count(int i); } //申明抽象类,继承I_4_A public abstract class I_4_L : I_4_A { //将方法申明为抽象方法,这样就表示等待被下面的方法来扩展 public abstract int J(int j); } //申明一个普通类,用来继承I_4_L抽像类和I_4_B接口 public class I_4_M : I_4_L, I_4_B { //实现抽象类的方法,其实这个方法,是I_4_A接口规定了的,不过被I_4_L给移交过来了 public int Count(int i) { return i*10; } //实现接口中的方法 public override int J(int j) { return j * 20; } } //----------------------使用接口---------------------------------- class Program { static void Main(string[] args) { I_4_L i4l = new I_4_M(); //实例化一个抽象类型I_4_L类型的对象 Console.WriteLine(i4l.J(10)); I_4_B i4b = new I_4_M(); //实例化接口I_4_B类型的对象 Console.WriteLine(i4b.Count(10));
Console.ReadLine(); } } |
小天:我刚才在VS中练习的时候,看到在被继承的接口下面出现了个绛紫色的小框,一点,居然提示上面显示实现接口和实现接口,这个是什么意思?如图4-33
图4-33
老田:这个很简单了,你都点击看看效果就知道了,如下
public class I_4_M : I_4_L, I_4_B { //实现 I_4_B 成员 public int Count(int i) { //。。。。。。。。。。。 } //显示实现 I_4_B 成员 int I_4_B.Count(int i) { //。。。。。。。。。。。 } } |
有什么区别?
这个主要用于,万一某个派生类继承的多个接口中有同样的方法这种情况,这就会导多个父接口打架了,都认为孩子是自己的。所以只好用显示实现了,这样也就不会误会了。
本文章为天轰穿原创作品,转载请注明出处及作者。