C# 显示接口实现(Explicitly Implement)
场景:一个类继承2个接口,2个接口都包含同一个名称&参数的方法
问题:不能起别名,如何兼顾这种情况
实现要点:Explicitly Implement时,不必加保护级别修饰符;要写上interface;
Sample:
class InterfaceTest:in1,in2
{
string isc="";
public string isclosed
{get{return"interfaceIsclosed";}}
string in2.isclosed
{get{return isc;}set{isc=value;}}
}
public interface in1
{string isclosed { get; }}
public interfacein2
{string isclosed { get; set; }
}
static void Main(string[] args)
{InterfaceTest test = new InterfaceTest();
((in2)test).isclosed = "newclosed";
Console.WriteLine("in1's isclosed:" + test.isclosed + "\n\r");
Console.WriteLine("in12's isclosed:" + ((in2)test).isclosed);
Console.ReadLine();}
http://www.winu.cn/space-14160-do-blog-id-24202.html
前两天在看MSDN里面关于迭代器的内容时,看到了一段代码,对其中接口的实现部分不太理解,其代码大致如下:
忽的一看,发现有点不对,类里面怎么有两个GetEnumerator()方法(12行和20行),而且参数都一样(都为空),仅仅只是返回值不同。如果是重载方法的话,理论上来说应该会有编译错误啊,但是把代码拷贝到编译器里面编译了一把,顺利通过编译。
试了一下,如果去掉第20行的方法IEnumerator IEnumerable.GetEnumerator()则出现编译错误,错误内容如下:
'GenericPractice.Program.Stack<T>' does not implement interface member 'System.Collections.IEnumerable.GetEnumerator()'. 'GenericPractice.Program.Stack<T>.GetEnumerator()' cannot implement 'System.Collections.IEnumerable.GetEnumerator()' because it does not have the matching return type of 'System.Collections.IEnumerator'.
错误信息的意思是说我没有实现接口System.Collections.IEnumerable,因为public IEnumerator<T> GetEnumerator()不能实现IEnumerable的IEnumerator GetEnumerator()方法。
因为IEnumerator<T>是继承自IEnumerator的。所以我刚开始以为,由于方法名和参数一样,只用实现 IEnumerator<T>中的方法就可以了。后来看了下MSDN知道如果要继承一个接口,则需要实现这个接口的方法以及这个接口的所有父接口的方法。
我总结了下接口实现的一些内容如下:
一、接口实现分为显式接口实现和隐式接口实现。
二者有一些不同,显式实现就是指通过指定接口名来实现方法,隐式实现是指通过一个相同的成员方法来实现接口方法。代码示例如下:
显示实现的方法不能直接通过类的实例调用,需要强制转换为接口的实例才能调用。 例如:
也就是说,如果是显示实现接口的方法,那么该方法不能作为类的实例的方法来调用,只能在类的内部使用,这也就是为什么显示实现的方法不用加“public”等成员限定符的原因,因为加不加没有任何意义。如果需要调用,需要先把类的实例转换为接口实例再调用。
另外,在试的过程还发现一个问题,如果类既有隐式实现也有隐式实现接口,那么隐式实现的方法将会被作为类的成员方法,显示实现的方法将会被作为接口的方法。这个结果也很符合常理。
二、实现多个接口时,各个接口中有完全相同方法的情况。
如果两个接口IA、IB中有一个完全相同的方法(返回值和参数都要相同,否则会被看成不同的方法),现在我们有一个类要去实现这两个接口,情况如下:
a. 如果是隐式实现,那么实现一个方法就可以了,这个方法会当作是对两个接口的实现。
b. 如果是显示实现,那么需要分别实现,各个接口的方法实现是独立的。
好像Java中不支持这种用法,会给一个编译错误。这也算是C#对Java一个改进的方面吧。具体的C#示例代码如下:
1 interface IA
2 {
3 void fun1();
4 }
5
6 interface IB
7 {
8 void fun1();
9 }
10
11 //隐式实现接口IA,IB
12 class ImplicitClass : IA, IB
13 {
14 public void fun1()
15 {
16 Console.WriteLine("public void fun1()");
17 }
18 }
19
20 //显式实现接口IA,IB
21 class ExplicitClass : IA, IB
22 {
23 void IA.fun1()
24 {
25 Console.WriteLine("void IA.fun1()");
26 }
27
28 void IB.fun1()
29 {
30 Console.WriteLine("void IB.fun1()");
31 }
32 }
33
34 //调用
35 static void Main(string[] args)
36 {
37 //显式实现接口的类的对象
38 ImplicitClass ImplicitObj = new ImplicitClass();
39
40 //隐式实现接口的类的对象
41 ExplicitClass ExplicitObj = new ExplicitClass();
42
43 //输出结果为 "public void fun1()"
44 ImplicitObj.fun1();
45
46 //输出结果为 "public void fun1()"
47 ((IA)ImplicitObj).fun1();
48
49 //输出结果为 "public void fun1()"
50 ((IB)ImplicitObj).fun1();
51
52 //输出结果为 "void IA.fun1()"
53 ((IA)ExplicitObj).fun1();
54
55 //输出结果为 "void IB.fun1()"
56 ((IB)ExplicitObj).fun1();
57 }
还有一种特殊情况,就是如果有隐式实现,并且有部分的显示实现,例如在隐式实现IA的同时类中还给出IB的显示实现。大家应该可以猜的出来,如果是IB的实例来调用方法,那么调用的方法就是IB的显示实现的方法。如果是类的实例来调用方法,那么调用的方法就是类中隐式实现的方法。
个人觉得C#这种处理接口方法同名的方式很自然、合理,用起来比较舒服。
三、实现从其它接口派生来的接口,并且该接口与其基类中有完全相同的方法。
这个和上面的情况非常类似,代码示例就不给出来了,遵循的原则是一样的:类中隐式实现的方法可以由类的实例来调用,如果没有显示的接口实现 ,那么接口的实例同样也可以调用这个隐式实现的方法;如果有显示实现,那么接口的实例调用的将会是显式实现的方法,类的实例不能调用显示实现的方法,但是可以在类的内部使用。
四、总结
我自己觉得这些没有太大的实践意义,例如像实现两个有相同方法的接口这种情况,实际工作中几乎不碰到,碰到的话也十有八九是设计的问题。主要是乍得一看不太了解,觉得有些新鲜所以花了点时间看了看,加强一下对语法和面向对象的理解。