博客园  :: 首页  :: 新随笔  :: 订阅 订阅  :: 管理

小天:接口主要是给类做父类的吗?它还能不能继承其它的接口呢?

       老田:当然是可以的,不过接口继承接口会有一个问题。通过前面的介绍也知道了,接口本身是不会去实现任何方法的。它只是规定了要实现那些方法,以及要什么样的材料(参数),能够生产什么样的产品(返回值)。于是,接口继承接口的结果就是越往后的接口所带的成员就越多了。例如,下面代码,

    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)

        {

            //。。。。。。。。。。。

        }

    }

       有什么区别?

       这个主要用于,万一某个派生类继承的多个接口中有同样的方法这种情况,这就会导多个父接口打架了,都认为孩子是自己的。所以只好用显示实现了,这样也就不会误会了。

 本文章为天轰穿原创作品,转载请注明出处及作者。