思路参照 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. JQ仿select框

    点击[cy_title]后弹出[cy_list]层,选中里面的元素把值赋给 [cy_title] 在[cy_list] 打开的时候,点击其他地方可以关闭: HTML: <div class=&q ...

  2. rem是如何实现自适应中的?

    使用rem 然后根据媒体查询实现自适应.跟使用JS来自适应也是同个道理,不过是js更精确一点.使用媒体查询: html { font-size: 62.5% } @media only screen ...

  3. ibatis 改下数据库连接

             <!--<dataSource name="iBatisNet" connectionString="data source= DESKTO ...

  4. 百度地图API示例之文本标注

    代码 <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" cont ...

  5. HttpClient入门

    HttpClient入门 HttpClient 是 Apache Jakarta Common 下的子项目,可以用来提供高效的.最新的.功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 H ...

  6. Unieap3.5-Grid翻页不提示修改

    <toolbar export="{defaultType:'server'}" paging="{onPagingModified:ssSettleCheck.o ...

  7. 浅谈Bootstrap自适应功能在Web开发中的应用

    随着移动端市场的强势崛起,web的开发也变得愈发复杂,对于个体开发者来说,自己开发的网站,在电脑.手机.Pad等上面都要有正常的显示以及良好的用户体验.如果每次都要自己去调整网页去匹配各个不同的客户端 ...

  8. dnw-linux的安装及使用

    <Tiny6410刷机指南>介绍了如何用USB线下载uboot,kernel,filesystem到开发板的nand flash,USB下载文件用到工具dnw.遗憾的是该教程提供的是win ...

  9. Linux多线程编程阅读链接

    1. 进程与线程的一个简单解释(阮一峰) 2. linux 多线程编程 3. Linux 的多线程编程的高效开发经验 (IBM)

  10. windows下如何修改远程登录端口

    windows下如何修改远程登录端口 windows远程桌面默认端口为3389,修改 方法如下:在"开始>运行"中输入"regedit" 点击“确定”,打 ...