思路参照 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#中基类与接口混合继承的疑问总结的更多相关文章

  1. 关于Java中基类构造器的调用问题

    在<Java编程思想>第7章复用类中有这样一段话,值得深思.当子类继承了父类时,就涉及到了基类和导出类(子类)这两个类.从外部来看,导出类就像是一个与基类具有相同接口的新类,或许还会有一些 ...

  2. 基类VS接口

    该篇引用 CLR via C# 中的13.11节. 应该设计基类还是接口,这个问题不能一概而论,下面提供一些指导性原则: 1. IS_A关系(指属于,例如汽车属于交通工具) vs CAN_DO关系(指 ...

  3. C++中基类的析构函数为什么要用virtual虚析构函数

    知识背景 要弄明白这个问题,首先要了解下C++中的动态绑定. 关于动态绑定的讲解,请参阅:  C++中的动态类型与动态绑定.虚函数.多态实现 正题 直接的讲,C++中基类采用virtual虚析构函数是 ...

  4. C++中基类虚析构函数的作用及其原理分析

    虚析构函数的理论前提是 执行完子类的析构函数,那么父类的虚构函数必然会被执行. 那么当用delete释放一个父类指针所实例化的子类对象时,如果没有定义虚析构函数,那么将只会调用父类的析构函数,而不会调 ...

  5. 详解C++中基类与派生类的转换以及虚基类

    很详细!转载链接 C++基类与派生类的转换在公用继承.私有继承和保护继承中,只有公用继承能较好地保留基类的特征,它保留了除构造函数和析构函数以外的基类所有成员,基类的公用或保护成员的访问权限在派生类中 ...

  6. koa 基础(十八)es6中的类、静态方法、继承

    1.app.js /** * es6中的类.静态方法.继承 */ // 定义Person类 class Person { constructor(name, age) { /*类的构造函数,实例化的时 ...

  7. koa 基础(十七)原生 JS 中的类、静态方法、继承

    1.app.js /** * 原生 JS 中的类.静态方法.继承 * es5中的类和静态方法 */ function Person(name, age) { // 构造函数里面的方法和属性 this. ...

  8. C#编程语言与面向对象——抽象基类与接口

    在一个类前加“abstract”关键字,此类就成为抽象类. 对应的,在一个方法前加“abstract”关键字,此方法就成为抽象方法. abstract class Fruit //抽象类 { publ ...

  9. 6、面向对象以及winform的简单运用(抽象基类与接口)

    抽象类与抽象方法 1.书写规范: 在类前面加上abstract关键字,就成为了抽象类:在一个方法前面加上abstract关键字,就成为了抽象方法(抽象方法不能有实现方法,直接在后面加分号) 例: ab ...

随机推荐

  1. python md5

    import hashlib import os 简单的测试一个字符串的MD5值 src = 'teststring' print (hashlib.md5(src).hexdigest().uppe ...

  2. js动态改变图片热区坐标,手机端图片热区自适应

    <img id='banner1' src="images/banner.jpg" usemap="#banner" border="0&quo ...

  3. 001Linux命令

    1.删除非空目录的命令:rm -rf [目录名],r表示迭代,f表示强制: 删除空目录:rmdir [目录名]: 删除文件:rm [文件名]: 2.用户管里类命令: (1)添加用户:useradd [ ...

  4. SQL笔记-第一章,数据库入门

    DBMS的分类DB2.Oracle.Microsoft SQL Server.Sybase SQLServer.Informix.MySQL数据库的结构元素库 database表 table列 col ...

  5. sql server2005 实现读写分离

    下面我们重点介绍Sql Server 2005是如何实现负载均衡的. Sql Server 2005的新特性 端到端拓扑的事务性复制 SQL Server 2005对端到端(P2P)拓扑结构上事务性的 ...

  6. Configuring Report Manager

     Steps to configure and get Reports in Report manager. 1. Enable getting Reports in Report Manager. ...

  7. phpQuery采集微信公众号文章乱码

    终于找到解决方案了,这是一个值得庆祝的事情.... 原来是因为微信在源码中加入了防采集代码<!--headTrap<body></body><head>< ...

  8. yii在TbGridView的td里面加入相应的下拉选项(转)

    当你需要在一个GridView渲染某一个复杂元素的时候(特别是在这种情况下,这是一个小部件),这就需要你在控制器中调用一个动作.例如你给一个GridView的定义这样的一列: <?php $th ...

  9. CKeditor的简单使用

    由于项目中要使用ckeditor 做个推荐功能,由于值设定到文本内容,就选择最基本的使用. 使用的版本为当前最新版本4.4.7,你需要下载两部分,一个是前台使用,一个是后台使用, 你可以到我的网盘中下 ...

  10. FileUpload控件「批次上传 / 多档案同时上传」的范例--以「流水号」产生「变量名称」

    原文出處  http://www.dotblogs.com.tw/mis2000lab/archive/2013/08/19/multiple_fileupload_asp_net_20130819. ...