一个关于C#中基类与接口混合继承的疑问总结
思路参照 http://www.cnblogs.com/allenlooplee/archive/2004/11/16/64553.html,对原文进行了简化和补充,感谢原作者。
问题很简单,如下所示:
有如下接口声明:
interface IC
{
void M();
}
类A实现了接口IC:
class A : IC
{
public void M()
{
Console.WriteLine("In class A");
}
}
那么问题来了,如下两种声明类B的方式有什么区别:
class B : A
{ }
class B : A, IC
{ }
这个问题,我一直没弄明白,只好写一段代码来验证。
首先,对继承自A类的B进行改造,如下所示:
class B : A
{
void M()
{
Console.WriteLine("In class B");
}
}
结果编译器出现如下提示:
好吧,将代码改为:
class B : A
{
public new void M()
{
Console.WriteLine("In class B");
}
}
结果运行后结果竟然是In class A。。。
那下面这样行不行呢?
class B : A
{
void IC.M()
{
Console.WriteLine("In class B");
}
}
结果这回,编译器直接报错了。。。
好吧,看来,直接继承自A的类B,是无法修改M的行为的。下面来看另外一种方式实现的B。
class B : A, IC
{
public new void M()
{
Console.WriteLine("In class B");
}
}
运行结果如下图所示:
好了,这回没问题,同样,按照下面这种方式来写,结果也正常:
class B : A, IC
{
void IC.M()
{
Console.WriteLine("In class B");
}
}
所以,结论就很明显了。
1、如果B仅继承自A,那么接口的方法定就无法在B中被修改。
2、如果B同时继承自A和接口,那么可以在B中实现自己的方法。
其实,上述结论1中,还不算是太准确,有一种方法可以在B中实现自己的方法定义,如下所示:
首先,修改方法A:
class A : IC
{
public virtual void M()
{
Console.WriteLine("In class A");
}
}
然后,修改B的实现:
class B : A
{
public override void M()
{
Console.WriteLine("In class B");
}
}
这样,运行起来就可以得到预期的结果了。
注意,下面这种写法也是错误的,知道问题在哪里吗?
class B : A, IC
{
new void M()
{
Console.WriteLine("In class B");
}
}
一个关于C#中基类与接口混合继承的疑问总结的更多相关文章
- 关于Java中基类构造器的调用问题
在<Java编程思想>第7章复用类中有这样一段话,值得深思.当子类继承了父类时,就涉及到了基类和导出类(子类)这两个类.从外部来看,导出类就像是一个与基类具有相同接口的新类,或许还会有一些 ...
- 基类VS接口
该篇引用 CLR via C# 中的13.11节. 应该设计基类还是接口,这个问题不能一概而论,下面提供一些指导性原则: 1. IS_A关系(指属于,例如汽车属于交通工具) vs CAN_DO关系(指 ...
- C++中基类的析构函数为什么要用virtual虚析构函数
知识背景 要弄明白这个问题,首先要了解下C++中的动态绑定. 关于动态绑定的讲解,请参阅: C++中的动态类型与动态绑定.虚函数.多态实现 正题 直接的讲,C++中基类采用virtual虚析构函数是 ...
- C++中基类虚析构函数的作用及其原理分析
虚析构函数的理论前提是 执行完子类的析构函数,那么父类的虚构函数必然会被执行. 那么当用delete释放一个父类指针所实例化的子类对象时,如果没有定义虚析构函数,那么将只会调用父类的析构函数,而不会调 ...
- 详解C++中基类与派生类的转换以及虚基类
很详细!转载链接 C++基类与派生类的转换在公用继承.私有继承和保护继承中,只有公用继承能较好地保留基类的特征,它保留了除构造函数和析构函数以外的基类所有成员,基类的公用或保护成员的访问权限在派生类中 ...
- koa 基础(十八)es6中的类、静态方法、继承
1.app.js /** * es6中的类.静态方法.继承 */ // 定义Person类 class Person { constructor(name, age) { /*类的构造函数,实例化的时 ...
- koa 基础(十七)原生 JS 中的类、静态方法、继承
1.app.js /** * 原生 JS 中的类.静态方法.继承 * es5中的类和静态方法 */ function Person(name, age) { // 构造函数里面的方法和属性 this. ...
- C#编程语言与面向对象——抽象基类与接口
在一个类前加“abstract”关键字,此类就成为抽象类. 对应的,在一个方法前加“abstract”关键字,此方法就成为抽象方法. abstract class Fruit //抽象类 { publ ...
- 6、面向对象以及winform的简单运用(抽象基类与接口)
抽象类与抽象方法 1.书写规范: 在类前面加上abstract关键字,就成为了抽象类:在一个方法前面加上abstract关键字,就成为了抽象方法(抽象方法不能有实现方法,直接在后面加分号) 例: ab ...
随机推荐
- python md5
import hashlib import os 简单的测试一个字符串的MD5值 src = 'teststring' print (hashlib.md5(src).hexdigest().uppe ...
- js动态改变图片热区坐标,手机端图片热区自适应
<img id='banner1' src="images/banner.jpg" usemap="#banner" border="0&quo ...
- 001Linux命令
1.删除非空目录的命令:rm -rf [目录名],r表示迭代,f表示强制: 删除空目录:rmdir [目录名]: 删除文件:rm [文件名]: 2.用户管里类命令: (1)添加用户:useradd [ ...
- SQL笔记-第一章,数据库入门
DBMS的分类DB2.Oracle.Microsoft SQL Server.Sybase SQLServer.Informix.MySQL数据库的结构元素库 database表 table列 col ...
- sql server2005 实现读写分离
下面我们重点介绍Sql Server 2005是如何实现负载均衡的. Sql Server 2005的新特性 端到端拓扑的事务性复制 SQL Server 2005对端到端(P2P)拓扑结构上事务性的 ...
- Configuring Report Manager
Steps to configure and get Reports in Report manager. 1. Enable getting Reports in Report Manager. ...
- phpQuery采集微信公众号文章乱码
终于找到解决方案了,这是一个值得庆祝的事情.... 原来是因为微信在源码中加入了防采集代码<!--headTrap<body></body><head>< ...
- yii在TbGridView的td里面加入相应的下拉选项(转)
当你需要在一个GridView渲染某一个复杂元素的时候(特别是在这种情况下,这是一个小部件),这就需要你在控制器中调用一个动作.例如你给一个GridView的定义这样的一列: <?php $th ...
- CKeditor的简单使用
由于项目中要使用ckeditor 做个推荐功能,由于值设定到文本内容,就选择最基本的使用. 使用的版本为当前最新版本4.4.7,你需要下载两部分,一个是前台使用,一个是后台使用, 你可以到我的网盘中下 ...
- FileUpload控件「批次上传 / 多档案同时上传」的范例--以「流水号」产生「变量名称」
原文出處 http://www.dotblogs.com.tw/mis2000lab/archive/2013/08/19/multiple_fileupload_asp_net_20130819. ...