接口映射的实现及原理

可以看出,每一个“方法()”,实际上都是不同的。
在“有接口的继承”中,接口将“Test.接口.方法()”进行了重新映射。这个映射是如何完成的呢?
看看如下的IL代码:
在采取使用它们自己的类作为访问入口时,代码实现如下:
没有接口的继承,它实现的方式如下:
.method public hidebysig instance void 方法() cil managed { // Code Size: 11 byte(s) .maxstack 1 L_0000: ldstr "\u6211\u53ea\u80fd\u591f\u4f7f\u7528 |
而有接口的继承,实现方式是这样的:
.method private hidebysig newslot virtual final instance void Test.接口.方法() cil managed { .override Test.接口::方法 // Code Size: 11 byte(s) .maxstack 1 L_0000: ldstr "\u8fd9\u5c31\u53eb\u505a\u63a5\u53e3\u7684\u91cd\u6620 |
在这里可以看出,有接口的继承实际上对“方法”进行override,但这个override是覆盖的接口的方法的实现成员,并非是类的方法成员。
然后,我们继续看看在客户类中对两者进行调用的IL
没有接口继承的IL
L_001d: newobj instance void Test.没有接口的继承::.ctor() //创建实例
L_0022: stloc.2
L_0023: ldloc.2
L_0024: callvirt instance void Test.没有接口的继承::方法()
有接口继承的IL
L_003a: newobj instance void Test.有接口的继承::.ctor() //创建实例
L_003f: stloc.s 有接口的继承1
L_0041: ldloc.s 有接口的继承1
L_0043: callvirt instance void Test.基类::方法()
如果是采取接口访问时,则状况如下:
没有接口继承的IL
L_0029: newobj instance void Test.没有接口的继承::.ctor()
L_002e: stloc.3
L_002f: ldloc.3
L_0030: callvirt instance void Test.接口::方法()
有接口继承的IL
L_0048: newobj instance void Test.有接口的继承::.ctor()
L_004d: stloc.s 接口3
L_004f: ldloc.s 接口3
L_0051: callvirt instance void Test.接口::方法()
----------------------------------------------------------------------------
注意一下上面标记颜色的部分,可以看出,采用不同的访问方式,实现的结果并不尽相同。也就是说,针对接口实现了的方法,与类本身自带的实现,是两回事,这种情况很类似于采用new关键字进行创建一个新的同名成员方法时遭遇的问题。
结果之所以会不同,是由于访问的方式不同的原因,如果采用“基类”来访问,很明显,这里获得的就是基类的成员实现。也就是说,这也是多态的一种体现,但并非不可预知或不可控制的。
看见有人说VB很难实现接口的映射,实际上并不是这样,要解释一下这个问题,这里不得不说一下,强类型的C#语法的含义。
“基类 objBase = new 基类();” 这种语法,表示的是使用“基类”来访问新建的“基类”的实例,换而言之,“基类 objDevired = new 没有接口的继承();”表示的就是使用基类来访问新建的“没有接口的继承”的实例。
接口的访问,也是如此,在原理上,将接口看作是一个十分特殊的抽象类,它与一般的抽象类的区别在于强制了成员的实现(接口的语法由编译器来验证的,在CLR并未提供限制性机制),所以,在有一些设计模式中,也可以看到采用了接口-抽象类-具体类的方式来绕开这类强制成员实现的检查,从而提高灵活性。
所以,VB.NET照样也可以完成接口映射,因为接口本身的实现机制仍旧是依赖于类的基本特征的。
示例伪代码如下:




























但就接口本身来说,是一个便利性的工具,在编程时的认识上,我们不应该将它与类视作“同一类东西”,它是对类的之间关系的一个描述。对于类本身的机制来说,继承与多态都是提供父子关系的纵向关系描述,而横向的关系描述,则反映得并不是很好,接口通过一定的实现机制,则部分性地弥补了这个空缺。
像代码中所描述那样,接口仅是作为一个便利性的工具存在,在面向接口的编程中,提供一切都围绕接口而进行,所以,在此类的编程模式下,可以采用接口为替换一个方法实现提供十分理想的方式,虽然这比起滥用继承并没有什么优势,但它是一个思想与观念上的转变,从本质上来说,接口映射与继承中的new一样,作为技巧用用可以,但它本身并不是一个值得推荐的方式。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix