实现和覆写虚方法的区别:接口中声明的成员默认不是虚方法。派生类不能覆写基类中实现的接口成员。接口可以被显式实现,这会使针对该类的公有成员隐藏起来。接口与虚方法的概念不同,用法也不同。

改变从基类继承的接口在派生类中的行为

  我们来看一个简单的例子:

 1         interface IMsg
 2         {
 3             void Message();
 4         }
 5         public class MyClass : IMsg
 6         {
 7             public void Message()
 8             {
 9                 Console.WriteLine("MyClass");
10             }
11         }
12
13         public class MyDerivedClass : MyClass
14         {
15             public new void Message()
16             {
17                 Console.WriteLine("MyDerivedClass");
18             }
19         }
20
21         public class EffectiveCSharp
22         {
23             public static void Main(string[] args)
24             {
25                 MyDerivedClass d = new MyDerivedClass();
26                 d.Message();
27                 IMsg m = d as IMsg;
28                 m.Message();
29
30                 Console.Read();
31             }
32         }

运行输出:

  我们发现,将MyDerivedClass的实例做了转换之后,调用Message()方法变成了该类基类Class的Message()方法——有时候我们常常需要创建接口,然后在基类中实现它们,并且在派生类中更改它们的实现,这时候我们该怎么办呢?这时候有两种办法可供选择。

1.将实现接口的基类中实现的接口成员定义成:virtual,并在派生类中override

 1         interface IMsg
 2         {
 3             void Message();
 4         }
 5         public class MyClass : IMsg
 6         {
 7             public virtual void Message()
 8             {
 9                 Console.WriteLine("MyClass");
10             }
11         }
12
13         public class MyDerivedClass : MyClass
14         {
15             public override void Message()
16             {
17                 Console.WriteLine("MyDerivedClass");
18             }
19         }
20
21         public class EffectiveCSharp
22         {
23             public static void Main(string[] args)
24             {
25                 MyDerivedClass d = new MyDerivedClass();
26                 d.Message();
27                 IMsg m = d as IMsg;
28                 m.Message();
29
30                 Console.Read();
31             }
32         }

运行输出:

2.将实现接口的基类定义成抽象类,并将实现的接口成员定义为抽象成员

  我们同时可以将派生类的重写方法定义成密封的防止其派生类再重写该方法:

 1         interface IMsg
 2         {
 3             void Message();
 4         }
 5         public abstract class MyClass : IMsg
 6         {
 7             public abstract void Message();
 8         }
 9
10         public class MyDerivedClass : MyClass
11         {
12             public sealed override void Message()
13             {
14                 Console.WriteLine("MyDerivedClass");
15             }
16         }
17
18         public class EffectiveCSharp
19         {
20             public static void Main(string[] args)
21             {
22                 MyDerivedClass d = new MyDerivedClass();
23                 d.Message();
24                 IMsg m = d as IMsg;
25                 m.Message();
26                 MyClass c = (MyClass)m;
27                 c.Message();
28                 Console.Read();
29             }
30         }

运行输出:

派生类继承基类中接口的实现

  其实派生类可以从基类中继承基类对接口的实现,因为派生类可以把该接口的声明成为其契约的一部分,即使它并没有实现任何该接口中成员的实现,只要类的某个公开可访问的方法与接口的签名相匹配,那么契约的条件即可满足,不过这种方法无法使用显示接口实现。例如下面的示例:

 1        interface IMsg
 2         {
 3             void Message();
 4         }
 5         public abstract class MyClass : IMsg
 6         {
 7             public virtual void Message()
 8             {
 9                 Console.WriteLine("MyClass");
10             }
11         }
12
13         public class MyDerivedClass : MyClass,IMsg
14         {
15         }
16
17         public class EffectiveCSharp
18         {
19             public static void Main(string[] args)
20             {
21                 MyDerivedClass d = new MyDerivedClass();
22                 d.Message();
23                 IMsg m = d as IMsg;
24                 m.Message();
25                 MyClass c = (MyClass)m;
26                 c.Message();
27                 Console.Read();
28             }
29         }

运行输出:

小节

实现接口拥有的选择要比创建和覆写虚函数多。我们可以为类层次创建密封类(sealed)的实现、虚实现或者抽象实现。我们还可以创建密封的实现,并在实现接口的方法中提供虚方法调用。我们也可以决定派生类应该如何及何时修改基类中实现的接口成员的默认行为。接口不是虚方法,而是一个单独的契约。

本文转自gyzhao博客园博客,原文链接:http://www.cnblogs.com/IPrograming/archive/2013/01/16/EffectiveCSharp_23.html,如需转载请自行联系原作者

《Effective C#》读书笔记——条目23:理解接口方法和虚方法的区别使用C#表达设计...相关推荐

  1. 《Effective C#》读书笔记——条目11:理解短小方法的优势C#语言习惯

    在应用程序开发过程中,开发者都力求写出更加高效的代码.但是当你想手工为C#编译器优化代码时,你的种种优化可能反倒会阻碍JIT进行更加高效的优化.因此,我们最好尽可能的写出最清晰的代码,将优化工作交给J ...

  2. Effective C++读书笔记 摘自 pandawuwyj的专栏

    Effective C++读书笔记(0)       Start   声明式(Declaration):告诉编译器某个东西的名称和类型,但略去细节.   std::size_t numDigits(i ...

  3. Effective STL 读书笔记

    Effective STL 读书笔记 标签(空格分隔): 未分类 慎重选择容器类型 标准STL序列容器: vector.string.deque和list(双向列表). 标准STL管理容器: set. ...

  4. more effective c++和effective c++读书笔记

    转载自http://bellgrade.blog.163.com/blog/static/83155959200863113228254/,方便日后自己查阅, More Effective C++读书 ...

  5. C#读书笔记之继承、接口与抽象类续

    C#读书笔记之继承.接口与抽象类 http://www.cnblogs.com/linjzong/articles/2717173.html 接下来说明最开始提出的问题:为什么要使用接口和抽象类? 刚 ...

  6. Effective Java 读书笔记(七):通用程序设计

    Effective Java 读书笔记七通用程序设计 将局部变量的作用域最小化 for-each 循环优于传统的 for 循环 了解和使用类库 如果需要精确的答案请避免使用 float 和 doubl ...

  7. Effective Java读书笔记(二)

    Effective Java 读书笔记 (二) 创建和销毁对象 遇到多个构造器参数时要考虑使用构建器 创建和销毁对象 何时以及如何创建对象? 何时以及如何避免创建对象? 如何确保它们能够适时地销毁? ...

  8. Machine Learning in Action 读书笔记---第4章 基于概率论的分类方法:朴素贝叶斯

    Machine Learning in Action 读书笔记 第4章 基于概率论的分类方法:朴素贝叶斯 文章目录 Machine Learning in Action 读书笔记 一.基于贝叶斯决策理 ...

  9. Effective Java读书笔记---四、类和接口

    四.对于所有对象都通用的方法 15.使类和成员的可访问性最小化 区分一个组件设计得好不好,唯一重要的因素在于,它对于外部的其他组件而言,是否隐藏了其 内部数据和其他实现细节 . 信息隐藏 -----& ...

  10. Effective Java 第三版读书笔记(类和接口)

    第15条.使类和成员的可访问性最小化 对于成员有四种可访问级别: 1.私有的(private)----- 只有在声明该成员的顶层类内部才可以访问这个成员. 2.包级私有的(package-privat ...

最新文章

  1. 高可用的Spring FTP上传下载工具类(已解决上传过程常见问题)
  2. python线程池及其原理和使用
  3. 达观数据分析平台架构和Hive实践——TODO
  4. java中怎么固定间距_java中的GridBagLayout是怎么调组件间距的...
  5. python中类的嵌套_python中的嵌套类 | 学步园
  6. php按需加载方式来增加程序的灵活度
  7. ubuntu 查看日历,日期
  8. android之APP模块编译
  9. django 1.8 官方文档翻译: 2-1-1 模型语法(初稿)
  10. MySQL 安装+管理
  11. linux的pending状态怎么退出,状态pending是什么意思
  12. 使用Houdini快速将图片转换成文字模型
  13. echarts 图表不能占满全屏
  14. 大话设计模式—访问者模式
  15. 微信小程序笔记(三)
  16. 百词斩*****笔试题目
  17. 数字媒体技术考点整理
  18. 工厂仪表定时拍照智能AI算法识别内网部署方案
  19. Java自学之路——构造器(Constructor)
  20. 中国在6G专利上再进一步,申请量占比达五成,遥遥领先,美国的希望落空

热门文章

  1. 程序设计实践(评注版) 评注者序
  2. pandas小记:pandas数据规整化-正则化、分组合并及重塑
  3. 现控笔记(五)稳定性与Lyapunov方法
  4. PPT中均匀分布各图形(水平或垂直)
  5. unknow host service.gradle.org, proxy settings in gradle
  6. Windows按键翻译
  7. Eclipse-eclipse导入新项目后,运行时找不到主类解决办法
  8. 1087 有多少不同的值 (20 分)—PAT (Basic Level) Practice (中文)
  9. Android Java编写布局
  10. better-scroll在vue中的使用