接口一个被我忽略的地方--接口重定向技术

习惯于用IDE生成接口方法了,右键点击"Implement Interface",生成所有的接口方法声明,还带个Region多方便啊.
今天看<<CLR Vir C#>>时才了解到自己是知其然不知其所有然啊.

 实现接口方法很简单,新手估计也都会,但怎么理解这个过程,不见得所有人都知道

ContractedBlock.gifExpandedBlockStart.gifBase class
None.gifclass Base : IDisposable
ExpandedBlockStart.gifContractedBlock.gif
dot.gif
ContractedSubBlock.gifExpandedSubBlockStart.gif    
IDisposable Members#region IDisposable Members
InBlock.gif    
public void Dispose()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        Console.WriteLine(
"Base's Dispose");
ExpandedSubBlockEnd.gif    }

ExpandedSubBlockEnd.gif    
#endregion

ExpandedBlockEnd.gif}

None.gif
None.gif

首先我们可以简单的认为Base类里有个Dispose()的方法.这个方法跟是不是IDisposable的成员,先理解为没有关系.当编译这个类的时候,编译器发现它实现了IDisposable接口,于是查找有没有跟其成员IDisposable.Dispose()同名,参数和返回类型完全匹配,并且是public的,如果找到就在IVMap里指向这个方法的入口(我猜的,这地方具体见http://www.microsoft.com/china/MSDN/library/netFramework/netframework/JITCompiler.mspx?mfr=true)如果没有就出个编译错误.

如果找到的方法前面有virtual关键字,编译器仍然认为是匹配的.如何没有virtual关键字,编译器默认的还会为其加上sealed.那么其子类是无法override的.如何想要override父类的Dispose()方法,最好是在Base中定义Dispose()时使用virtual.当然如果我们没有权利改写Base类,我们可以让其子类同样继承自IDisposable,然后改写方法.这点已经有很多人谈论过了,估计大家基本都明白.不了解的可以gongle it!
ContractedBlock.gifExpandedBlockStart.gifDerived
None.gifclass Derived : Base, IDisposable
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    
public void Dispose()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        Console.WriteLine(
"Derived's Dispose");
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

现在问题来了,我们是真的改写了父类的Dispose()方法吗?
测试一下:
Base c = new Derived();
c.Dispose();
结果你可以发现输出的是: Base's Dispose.当时我觉得很奇怪,后来静下来想想原来可以这么理解.
就如我开始理解接口实现过程一样,对于上面的代码我们可以直接忽略接口的存在,等效如下

ContractedBlock.gifExpandedBlockStart.gifRemove Interface
None.gifclass Base 
ExpandedBlockStart.gifContractedBlock.gif
dot.gif
InBlock.gif    
public void Dispose()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        Console.WriteLine(
"Base's Dispose");
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif
None.gif
class Derived : Base 
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    
public void Dispose()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        Console.WriteLine(
"Derived's Dispose");
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif
None.gif

这样大家应该都知道为什么输出是Base's Dispose,如果不知道可以去查看 "今天你多态了吗"一文,说的很详细了.
回过来看我们刚才的代码,编译的时候有个警告:   'Program.Derived.Dispose()' hides inherited member 'Program.Base.Dispose()'. Use the new keyword if hiding was intended. 
是不是把Dispose()看成只是类的方法更容易理解呢.只是通过接口调用的时候指向了这个方法的入口而已.

我以为如下实现Derived类会更好些,不会让你产生误解,以为Derived  override了Base类的Dispose()方法

ContractedBlock.gifExpandedBlockStart.gif显示实现接口
None.gifclass Derived : Base, IDisposable
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    
void IDisposable.Dispose()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        Console.WriteLine(
"Derived's Dispose");
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

对于如下代码不要期待能输出Derived's Dispose结果.当然如果CallDispose()传入的参数类型是IDisposable,就当我没说过
static void Main(string[] args)
{
    Derived c = new Derived();
    CallDispose(c);
}
private static void CallDispose(Base b)
{
    b.Dispose();
}

要不然你得这样
private static void CallDispose(Base b)
{
    ((IDispose))b.Dispose();
}
但是你会觉得很别扭.当然 CallDispose(Base b)定义成这样本身就是个不好的设计.

具体大家可以看看<<CLR Vir C#>>14章,我想对于你理解接口实现的整个过程会有莫大的帮助

转载于:https://www.cnblogs.com/anders06/archive/2007/06/12/780719.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/364009.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java extends throws_继承,方法签名,方法重写和throws子句

容易记住访问修饰符可以从限制更改为限制更少&#xff0c;例如从受保护到公共&#xff0c;但反之亦然throws签名可以是从父异常更改为子异常类&#xff0c;但反之亦然此代码有效public class A {protected String foo() throws Exception{return "a";}class B extend…

[BZOJ]4071: [Apio2015]巴邻旁之桥

题解: 首先 明确 如果处于同一区域时 直接统计贡献即可 不用过桥 对k分情况讨论: 当k1时 假设桥的位置是 p 那么 $$ \sum_{i1}^n |x_i-p||y_i-p| $$ 很显然当对于 所有x,y排序后的中位数是最优的选择位置 具体证明可以模拟一下 当k2时 假设桥的位置是$p_1$和$p_2$ $$ \su…

vue 学习之路 —— 图片的引入

问题记录&#xff1a;在img中动态设置了src后&#xff0c;图片路径找不到 原因&#xff1a;vue中动态生成的路径无法被url-loader解析到 解决方法&#xff1a; 1、将图片放在static文件夹&#xff0c;然后正常解析 2、将图片使用import方法引入 3、 采用背景图做法&#xff0c;…

跟踪异常–第5部分–使用Spring进行计划

看来我终于快要结束本系列有关使用Spring进行错误跟踪的博客了&#xff0c;对于那些还没有阅读该系列博客的人&#xff0c;我正在编写一个简单但几乎具有工业实力的Spring应用程序&#xff0c;扫描日志文件中的异常&#xff0c;然后生成报告。 在本系列的第一个博客中&#xff…

java.util.hashmap_java.util.HashMap中的无限循环

我在这里经常有一些Vaadin代码阻塞,我不知道问题是什么&#xff1a;Thread 7892: (state IN_JAVA)- java.util.HashMap.getEntry(java.lang.Object) bci61, line349 (Compiled frame; information may be imprecise)- java.util.HashMap.containsKey(java.lang.Object) bci2, …

APP测试理论知识点

什么是APP测试&#xff1f; App测试就是软件工程师对这类应用软件进行功能测试&#xff0c;性能测试&#xff0c;安全性测试以及兼容性测试等。 对于app测试我们一般采用的是黑盒测试方法&#xff0c;也会在必要的时候进行自动化测试以及性能测试&#xff0c;丙炔对于app还会有…

超大超长图片居中显示且放大缩小无影响

1. 超大图片居中显示 1.1 放大缩小都居中显示 <!DOCTYPE html><html lang"en"><head><meta charset"UTF-8"><title>Document</title><style>body {overflow-x: hidden;}.top-banner .banner-list a {display: b…

蘋果的秘密武器

蘋果公司(Apple)在電腦操作平台之戰中負於微軟公司 (Microsoft)已經過去很多年了。如今﹐90%以上的筆記本電腦和台式電腦在使用微軟的Windows操作系統。然而近幾年來﹐蘋果公司對Windows主宰的世界發起突然襲擊﹐它的武器就是Windows版的iTunes﹐一個免費的媒體管理、儲存和播放…

如何使用NodeManager来控制WebLogic Server

在上一篇文章中 &#xff0c;您已经了解了如何启动WebLogic管理员和多个托管服务器。 该指令的一个缺点是这些进程将从前台开始&#xff0c;而STDOUT则打印在终端上。 如果打算将这些服务器作为后台服务运行&#xff0c;则可能需要尝试使用WebLogic节点管理器wlscontrol.sh工具…

php接口开发 安全_PHP开发api接口安全验证的实例讲解

php的api接口在实际工作中&#xff0c;使用PHP写api接口是经常做的&#xff0c;PHP写好接口后&#xff0c;前台就可以通过链接获取接口提供的数据&#xff0c;而返回的数据一般分为两种情况&#xff0c;xml和json,在这个过程中&#xff0c;服务器并不知道&#xff0c;请求的来源…

树:重建二叉树

题目描述 输入某二叉树的前序遍历和中序遍历的结果&#xff0c;请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6}&#xff0c;则重建二叉树并返回。 /// 1/// …

css随堂笔记(一)

Css初体验第一天 1 css初识&#xff1a;css主要用于设置HTML页面中文本内容&#xff0c;图片的外形&#xff0c;以及版面的布局等外观显示样式 Css样式规范&#xff1a;h1{属性&#xff1a;值} 2 css的三总书写方式&#xff1a;1 行内样式 将样式写在标签里面,只能作用于当前标…

关于全排列

嗯... 关于全排列&#xff0c;有很多种种做法... 嗯.... 那什么叫全排列呢&#xff1f;&#xff1f;&#xff01;&#xff01; 从n个不同元素中任取m&#xff08;m≤n&#xff09;个元素&#xff0c;按照一定的顺序排列起来&#xff0c;叫做从n个不同元素中取出m个元素的一个排…

[Java]如何安排任务间隔运行

应用程序中经常需要在后台运行某些特定任务以在一定间隔内完成某些工作。 该示例可以是&#xff0c;服务在后台运行以清理应用程序&#xff0c;就像我们有Java Garbage集合一样。 在本文中&#xff0c;我将向您展示3种不同的方法来实现这一目标 他们如下 使用简单的线程 使…

Sky Line 与 ArcEngine的粘合剂 Composite UI AB?

如今的goverment领导们觉得地图都太抽象&#xff0c;只有google Earth式的应用能引起他们的兴趣&#xff0c;作为为公仆服务的我们自然要学习掌握3D GIS技术来提高zf的执政能力了&#xff0c;于是Sky Line来了&#xff0c;拿到开发手册的时候觉得接口不多应该很容易开发&#x…

php if终止,php判断用户是否掉线及关闭网页的方法分享

要实现判断用户已掉线并关闭网页&#xff0c;主要用到方法connection_status 和 connection_aborted。通过一个例子&#xff0c;来了解下它们的用法:echo str_repeat(" ",300);//以下不可省略&#xff0c;否则用户断线&#xff0c;php(线程)立即终止&#xff0c;不会…

默认方法一种扩展旧代码的方法

如您所知&#xff0c;Java的新版本于2014年3月18日发布&#xff0c;我将介绍一系列文章来演示其新功能&#xff0c;也许在某些方面&#xff0c;我将谈论我的想法和批评。 我认为重要的第一个功能是“默认方法”&#xff0c;在所有Java语言的先前版本中&#xff0c;接口只能包含…

vue 如何点击按钮返回上一页

1&#xff0c;vue 如何点击按钮返回上一页呢&#xff1f; 这是vue挂载的范围html代码 <div click"goOff()">返回</div> 下面是点击返回的方法 第一种只返回上一页 goOff(){ this.$router.go(-1); }, 第二种 返回上一页&#x…

2007白领职场成功需要哪“十商”

1.德商(MQ)&#xff1a;指一个人的道德人格品质。德商的内容包括体贴、尊重、容忍、宽容、诚实、负责、平和、忠心、礼貌、幽默等各种美德。 2.智商(IQ)&#xff1a;是一种表示人智力高低的数量指标。也可以表现为一个人对知识的掌握程度&#xff0c;反映人的观察力、记忆力、思…

Remove Element - LeetCode

目录 题目链接注意点解法小结题目链接 Remove Element - LeetCode 注意点 输入的数组是无序的解法 解法一&#xff1a;使用了erase函数&#xff0c;将等于val的值移除。时间复杂度为O(n) class Solution { public:int removeElement(vector<int>& nums, int val) {fo…