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#这种处理接口方法同名的方式很自然、合理,用起来比较舒服。

 

     三、实现从其它接口派生来的接口,并且该接口与其基类中有完全相同的方法。

      这个和上面的情况非常类似,代码示例就不给出来了,遵循的原则是一样的:类中隐式实现的方法可以由类的实例来调用,如果没有显示的接口实现 ,那么接口的实例同样也可以调用这个隐式实现的方法;如果有显示实现,那么接口的实例调用的将会是显式实现的方法,类的实例不能调用显示实现的方法,但是可以在类的内部使用。

 

      四、总结

     我自己觉得这些没有太大的实践意义,例如像实现两个有相同方法的接口这种情况,实际工作中几乎不碰到,碰到的话也十有八九是设计的问题。主要是乍得一看不太了解,觉得有些新鲜所以花了点时间看了看,加强一下对语法和面向对象的理解。

posted on 2012-11-23 14:08  shwang  阅读(1590)  评论(1编辑  收藏  举报