思路参照 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. 【Linux】部署cobbler

    环境Centos 6.3,本地挂载镜像配置本地yum源 yum -y install dhcp httpd xinetd tftp-server http://dl.fedoraproject.org ...

  2. @media screen解决移动web开发的多分辨率问题

    当今移动设备的发展已经越来越迅速,移动web开发的需求也越来越多多.许多大平台.大门户都纷纷推出了自己的移动web版网站. 随着移动设备飞速的发展,移动产品的屏幕规格越来越多.从几年前的320×240 ...

  3. c# winform 关于DataGridView的一些操作(很全,绝对够用)

    转自:http://heisetoufa.iteye.com/blog/405317 设置字段名 设置字段值 设定单元格表示 Error图标 设定当前单元格 取得当前单元格内容 取得当前单元格的列 I ...

  4. 调试时屏蔽JavaScript库代码 –Chrome DevTools Blackbox功能介绍

    代码难免会有Bug,每次我们在Chrome调试代码时,总是会进入各种各样的库代码(比如jQuery.Zepto),但实际上很多时候我们并不希望这样,要是能把这些库代码“拉黑”多好啊. 广大码农喜闻乐见 ...

  5. grub丢失的修复

    使用安装光盘进入rescure模式,经过配置后进入一个bashbash# grubgrub> root (hd0,6)grub> setup (hd0)重启即可

  6. 说一个Sublime Text 2插件、emmet(原名:zen Coding)

    工具/原料 sublime Text 2 安装emmet插件 方法/步骤 生成html文档初始结构: !<tab> <!doctype html> <html lang= ...

  7. jQuery下拉友情链接美化效果代码分享

    这篇文章主要介绍了jQuery下拉友情链接美化效果,很实用的代码,推荐给大家,有需要的小伙伴可以参考下. 文实例讲述了jQuery下拉友情链接美化效果,jQuery下拉友情链接美化代码是一款基于jQu ...

  8. (一)、NodeJS (转载)

    NodeJS基础                                                 ------ 转载自阿里巴巴 什么是NodeJS JS是脚本语言,脚本语言都需要一个解 ...

  9. POJ C++程序设计 编程题#1 大整数的加减乘除

    编程题#4:大整数的加减乘除 来源: POJ (Coursera声明:在POJ上完成的习题将不会计入Coursera的最后成绩.) 注意: 总时间限制: 1000ms 内存限制: 65536kB 描述 ...

  10. C#反射动态调用dll中的方法

    //加载程序集(dll文件地址),使用Assembly类 Assembly assembly = Assembly.LoadFile(AppDomain.CurrentDomain.BaseDirec ...