您的位置:首页 > 编程语言 > C#

天轰穿C# -vs2010 - 04面向对象的编程之多重继承 【原创】

2013-02-04 14:05 387 查看
小天:接口主要是给类做父类的吗?它还能不能继承其它的接口呢?

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

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)

{

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

}

}

有什么区别?

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

本文章为天轰穿原创作品,转载请注明出处及作者。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐