关于接口和继承的奇怪问题

huwei001982 2008-06-20 09:11:34
    /// <summary>
/// 接口
/// </summary>
public interface ITest
{
void Test();
}
/// <summary>
/// 基类, 实现了 ITest 接口
/// </summary>
public class clsBase : ITest
{
public void Test()
{
Console.WriteLine("Base's Test!");
}
}

/// <summary>
/// 派生类
/// </summary>
public class clsDerive : clsBase, ITest
{
//此时编译时会报一个“Test.clsDerive.Test()' hides inherited member 'Test.clsBase.Test()'”编译器警告
//这个是正常的
public void Test()
{
Console.WriteLine("Derive's Test!");
base.Test();
}
}

//测试代码
{
ITest cls = new clsDerive();
cls.Test();
//此时居然打印出“Derive's Test!”, 也就是调用的是派生类的方法
//这个我是不能理解的,应该调用基类的方法才对, 因为派生类的 Test 隐藏了基类的方法
//但如果 clsDerive 类不从 ITest 接口继承, 即这样申明
public class clsDerive : clsBase //,ITest
//则结果是正常的, 打印出“Base's Test!”

//为什么会有这两种结果?
}
...全文
186 25 打赏 收藏 转发到动态 举报
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
mogui_ 2008-06-21
  • 打赏
  • 举报
回复
不在学校吗?
回去吧!!!!
fsy123456accp 2008-06-20
  • 打赏
  • 举报
回复
搞 搞
搞 搞
搞 搞
搞 搞
晕了吧
yeahspyme 2008-06-20
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 huwei001982 的回复:]
楼上的各位,我已经明确说明我知道它是隐藏的了, 但还是谢谢你们找来一些关于“隐藏”的资料

我关心的是, 为什么派生类申明 ITest 接口和 不申明 ITest 接口, 执行情况不一样
[/Quote]
之所以不一样是因为你是通过ITest来访为派生类的,如果派生类没有实现ITest,派生类就只能作为基类来看待了,因为派生类从基类那儿获得对ITest的实现,也就是说,

ITest cls = new clsDerive();
cls.Test();

相当于

ITest cls = new clsDerive();
((clsBase))cls.Test();

将clsDerive cast 成 clsBase类型再调用Test()
wisdomqq 2008-06-20
  • 打赏
  • 举报
回复
基础问题。。。。。。。。。。。。。。。。。。
hylovett 2008-06-20
  • 打赏
  • 举报
回复
纯顶..................
cacar2008 2008-06-20
  • 打赏
  • 举报
回复
ClsBase已经继承了接口,clsDerive继承了ClsBase等于也继承了接口了

如果需要重写方法,则在ClsBase用虚方法;
ypacyhero 2008-06-20
  • 打赏
  • 举报
回复
真不知道你到底要测试什么东东。。

基类实现了接口,子类从基类派生,,子类又去实现接口。。

真搞不清你要干什么,要测什么。。

每种情况都不一样。。

我肯定的只是一种情况。。。
huwei001982 2008-06-20
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 ypacyhero 的回复:]
因为你的 clsDerive类的public void Test()方法实际上等于 public new void Test()。。

所以说肯定是那样的结果。。。

[/Quote]
----------------------------------
先别这么肯定啊, 呵呵, 你试试在派生类的声明上加个 ITest, 则还是调用派生类地方法
fuadam 2008-06-20
  • 打赏
  • 举报
回复
我的理解是clsBase实现了ITest接口,那么clsDerive就没法再次实现了,所以要么clsBase的Test函数式virtual的要么 clsDerive基础了ITest接口,才能正确。
huwei001982 2008-06-20
  • 打赏
  • 举报
回复
楼上的各位,我已经明确说明我知道它是隐藏的了, 但还是谢谢你们找来一些关于“隐藏”的资料

我关心的是, 为什么派生类申明 ITest 接口和 不申明 ITest 接口, 执行情况不一样
fuadam 2008-06-20
  • 打赏
  • 举报
回复
clsDerive 加 ITest 和不加应该是一样的
===========================================
是不一样的,因为clsBase已经实现了ITest接口所以,要么clsBase的Test函数式virtual的要么 clsDerive基础了ITest接口,才能正确。
QQQQAnnie 2008-06-20
  • 打赏
  • 举报
回复
我同事帮我找的在MSDN上很清楚讲的

C# 允许派生类包含与基类方法名称相同的方法。

基类方法必须定义为 virtual。

如果派生类中的方法前面没有 new 或 override 关键字,则编译器将发出警告,该方法将有如存在 new 关键字一样执行操作。

如果派生类中的方法前面带有 new 关键字,则该方法被定义为独立于基类中的方法。

如果派生类中的方法前面带有 override 关键字,则派生类的对象将调用该方法,而不调用基类方法。

可以从派生类中使用 base 关键字调用基类方法。

override、virtual 和 new 关键字还可以用于属性、索引器和事件中。

GhostAdai 2008-06-20
  • 打赏
  • 举报
回复
Test.clsDerive.Test()' hides inherited member 'Test.clsBase.Test()'
--------------------------------------------------------------------
这不是已经警告你clsDerive.Test()方法已经隐藏了基类成员clsBase.Test()方法了嘛,相当于clsDerive.Test()的声明是new的声明,而不是override。调用cls.Test()的结果当然就是“Derive's Test!”了
ypacyhero 2008-06-20
  • 打赏
  • 举报
回复
因为你的 clsDerive类的public void Test()方法实际上等于 public new void Test()。。

所以说肯定是那样的结果。。。
ypacyhero 2008-06-20
  • 打赏
  • 举报
回复
//此时编译时会报一个“Test.clsDerive.Test()' hides inherited member 'Test.clsBase.Test()'”编译器警告


这么大的警告。。。。。。。。。。。。。。

****已经隐藏了继承成员****
huwei001982 2008-06-20
  • 打赏
  • 举报
回复

/// <summary>
/// 派生类
/// </summary>
public class clsDerive : clsBase, ITest
{
//此时编译时会报一个“Test.clsDerive.Test()' hides inherited member 'Test.clsBase.Test()'”编译器警告
//这个是正常的
public void Test()
{
Console.WriteLine("Derive's Test!");
//base.Test(); //这一行是多余的, 忘了去掉了
}
}



第二个问题
因为clsDerive 类没有实现ITest的方法
-------------------------------------------------
clsDerive 是从 clsBase 种继承的, 不是相当于实现了 ITest 吗

nnoovvee 2008-06-20
  • 打赏
  • 举报
回复
xuexi.........................
QQQQAnnie 2008-06-20
  • 打赏
  • 举报
回复
刚才同事提醒我这块,我觉得对

//此时编译时会报一个“Test.clsDerive.Test()' hides inherited member 'Test.clsBase.Test()'”编译器警告


警告已经把clsBase hide了,呵呵
starts_2000 2008-06-20
  • 打赏
  • 举报
回复
第二个问题
因为clsDerive 类没有实现ITest的方法,注意上面说的new,相当于是clsDerive 的新方法,只是碰巧跟前面的函数同名了,
这就是为什么给你警告的原因。
但clsDerive 的基类clsBase p这、实现了接口的方法,所以就调用基类的方法。

最后,你改成这样看看效果,有助于你理解:

public class clsDerive : clsBase , ITest
{
public new void Test()
{
Console.WriteLine("Derive's Test!");
base.Test();
}

#region ITest 成员

void ITest.Test()
{
Console.WriteLine("Derive's Test!"); ;
}

#endregion
}
starts_2000 2008-06-20
  • 打赏
  • 举报
回复
[code=C#[
public void Test()
{
Console.WriteLine("Derive's Test!");
base.Test();
}
[/code]

ITest cls = new clsDerive();
cls.Test();

你这个输出应该是:
Derive's Test!
Base's Test!
因为上面的方法相当于

public new void Test()
{
Console.WriteLine("Derive's Test!");
base.Test();
}

重写了基类的方法。

加载更多回复(5)

110,533

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧