小天:接口主要是给类做父类的吗?它还能不能继承其它的接口呢?
老田:当然是可以的,不过接口继承接口会有一个问题。通过前面的介绍也知道了,接口本身是不会去实现任何方法的。它只是规定了要实现那些方法,以及要什么样的材料(参数),能够生产什么样的产品(返回值)。于是,接口继承接口的结果就是越往后的接口所带的成员就越多了。例如,下面代码,
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)
{
//。。。。。。。。。。。
}
}
|
有什么区别?
这个主要用于,万一某个派生类继承的多个接口中有同样的方法这种情况,这就会导多个父接口打架了,都认为孩子是自己的。所以只好用显示实现了,这样也就不会误会了。
本文章为天轰穿原创作品,转载请注明出处及作者。
|
请发表评论