C#中的接口
本文将通过以下四个
案例
全员育人导师制案例信息技术应用案例心得信息技术教学案例综合实践活动案例我余额宝案例
来分析 C#中的接口究竟是如何工作的。
111
1
、公有方法实现接口方法
尽管C#在定义接口时不用指明接口方法的访问控制方式,但默认接口方法均为 public 型(这
可以从反编译的 IL代码中看到)。下面是使用 Reflector 查看的接口 IL 代码
.class private interface abstract auto ansi IControl
{
.method publicpublicpublic
public
hidebysig newslot abstract virtual inst
ance void Paint() cil managed
{
}
}
实现接口的类需要实现所有接口方法。通常情况下,接口的实现方法也为 public型。如下案
例:
using System ;
interface IControl
{
void Paint();
}
public class EditBox: IControl
{
publicpublicpublic
public
void Paint()
{
Console.WriteLine("Pain method is called!");
}
}
class Test
{
static void Main()
{
EditBox editbox = new EditBox();
editbox.Paint();editbox.Paint();editbox.Paint();
editbox.Paint();
((IControl)editbox).Paint();((IControl)editbox).Paint();((IControl)editbox).Paint();
((IControl)editbox).Paint();
}
}
程序的执行结果为:
Pain method is called!
Pain method is called!
接口就好像是关系型数据库中的一对多表,一个接口对应多个接口方法,每个接口方法又对
应虚拟方法表(VMT)中的某个公有或私有方法。上面代码在内存中的镜像可由下图描述:
从图中我们可以看到直接对 Paint方法的调用以及通过接口对 Paint方法的调用。可见通过
接口对方法进行调用需要多出一道转换工作,因此执行效率不如直接调用。
222
2
、私有方法不能实现接口方法
如果想将接口方法直接实现为私有方法是办不到的。下面的 EditBox的代码中 Paint方法没
有特殊说明,默认为 private,导致代码无法执行:
using System ;
interface IControl
{
void Paint();
}
public class EditBox: IControl
{
voidvoidvoid
void
Paint()Paint()Paint()
Paint()
{
Console.WriteLine("Pain method is called!");
}
publicpublicpublic
public
voidvoidvoid
void
ShowPaint()ShowPaint()ShowPaint()
ShowPaint()
{
this.Paint();
((IControl)this).Paint();((IControl)this).Paint();((IControl)this).Paint();
((IControl)this).Paint();
}
}
class Test
{
static void Main()
{
EditBox editbox = new EditBox();
editbox.ShowPaint();
}
}
程序在编译时将显示如下编译错误:““EditBox”不会实现接口成员“IControl.Paint()”。
“EditBox.Paint()”或者是静态、非公共的,或者有错误的返回类型。”
为什么会这样呢?如图:
这是由于接口
规范
编程规范下载gsp规范下载钢格栅规范下载警徽规范下载建设厅规范下载
中的方法默认的访问权限是 public,而类中的默认访问权限是 default,
也就是说 private,因此导致权限范围收缩,两者权限并不相同,所以必须将类的权限调整为
public才可以使上面的代码得以执行。
333
3
、实现专门的接口方法(111
1
)
代码如下:
using System ;
interface IControl
{
void Paint();
}
public class EditBox: IControl
{
voidvoidvoid
void
Paint()Paint()Paint()
Paint()
{
Console.WriteLine("Pain method is called!");
}
voidvoidvoid
void
IControl.Paint()IControl.Paint()IControl.Paint()
IControl.Paint()
{
Console.WriteLine("IControl.Pain method is called!
");
}
public void ShowPaint()
{
this.Paint();
((IControl)this).Paint();
}
}
class Test
{
static void Main()
{
EditBox editbox = new EditBox();
editbox.ShowPaint();
//editbox.Paint();//editbox.Paint();//editbox.Paint();
//editbox.Paint();
((IControl)editbox).Paint();((IControl)editbox).Paint();((IControl)editbox).Paint();
((IControl)editbox).Paint();
}
}
EditBox类拥有一私有 Paint方法,但这并不是接口方法的实现(上例已经分析过)。EditBox
类中还包含了一“void IControl.Paint()”方法, 是该方法复写了接口的 Paint方法,该方法是
私有的(通过 IL代码可以看出)。
注意:“void IControl.Paint()”前不能加任何的修饰限定符号,诸如 public、private 等 ,
这在 C#的语法中是不允许的。该方法反编译得到的 IL代码如下:
.class public auto ansi beforefieldinit EditBox
extends object
implements IControl
{
.......
.method privateprivateprivate
private
hidebysig newslot virtual final ins
tance void IControl.Paint() cil managed
{
.override.override.override
.override
IControl::PaintIControl::PaintIControl::Paint
IControl::Paint
}
}
程序运行时内存中的镜像可简化表示为:
程序执行结果如下:
Pain method is called!
IControl.Pain method is called!
IControl.Pain method is called!
我们之所以可以通过((IControl)editbox).Paint()方法访问到代码是因为接口方法
Paint是公有的。但是我们不能通过 editbox.Paint()方法访问到代码是因为 EditBox的
Paint方法是私有的。 在 EditBox内部,通过 ShowPaint方法可以同时访问私有的 Paint方
法与接口 IControl.Paint 方法。
444
4
、实现专门的接口方法(222
2
)
如果 EditBox中的 Pait方法为公有并且同时提供了 IControl.Paint方法,程序将是如何运
行的呢?代码如下:
using System ;
interface IControl
{
void Paint();
}
public class EditBox: IControl
{
publicpublicpublic
public
voidvoidvoid
void
Paint()Paint()Paint()
Paint()
{
Console.WriteLine("Pain method is called!");
}
voidvoidvoid
void
IControl.Paint()IControl.Paint()IControl.Paint()
IControl.Paint()
{
Console.WriteLine("IControl.Pain method is called!
");
}
}
class Test
{
static void Main()
{
EditBox editbox = new EditBox();
editbox.Paint();editbox.Paint();editbox.Paint();
editbox.Paint();
((IControl)editbox).Paint();((IControl)editbox).Paint();((IControl)editbox).Paint();
((IControl)editbox).Paint();
}
}
程序执行结果如下:
Pain method is called!
IControl.Pain method is called!
程序执行时内存布局如下:
可见,EditBox中公有的 Paint方法并不是接口实现方法,真正的接口实现方法是
IControl.Paint,这将导致 editbox.Paint()方法与((IControl)editbox).Paint()的
执行结果并不一样。
555
5
、结论
接口方法的实现通常是通过类中的公有方法实现的;
在一些特殊情况下(代码隐藏、一个类实现的两个接口具有相同的接口方法等),需要专门
实现某个接口的方法。
1、公有方法实现接口方法
2、私有方法不能实现接口方法
3、实现专门的接口方法(1)
4、实现专门的接口方法(2)
5、结论