C#的多态问题,大家看看这个问题吧

shanyou 2003-11-20 09:20:15
Token.cs
using System;
namespace ParamsArray
{
/// <summary>
/// Token 的摘要说明。
/// </summary>
public class Token
{
public Token()
{
//
// TODO: 在此处添加构造函数逻辑
//
test = "Hello world";
}

public virtual string name()
{

return test;
}
private string test;

}
public class IdentifierToken : Token
{
public IdentifierToken(string Iden) :base()
{
IdenToken = Iden;
}

public virtual string name()
{

return IdenToken;

}
private string IdenToken ;
}

}
Tokentest.cs
using System;

namespace ParamsArray
{
/// <summary>
/// Class1 的摘要说明。
/// </summary>
class Utiltest
{
public static void Method(Token t)
{
Console.WriteLine(t.name());
}
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main(string[] args)
{
//
// TODO: 在此处添加代码以启动应用程序
//
IdentifierToken variable = new IdentifierToken("Variale");
Method(variable);

}
}
}

上面的程序,输出的结果是“Hello world",而不是Variale;
没有体现多态的方法,这是为什么?
...全文
112 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
coolpine 2003-11-20
  • 打赏
  • 举报
回复
gOODiDEA(无语)的就是正解
ML20 2003-11-20
  • 打赏
  • 举报
回复
只要把IdentifierToken里的
public virtual string name()
{

return IdenToken;

}
改为
public override string name()
{

return IdenToken;

}
即可
storm97 2003-11-20
  • 打赏
  • 举报
回复
类IdentifierToken 中的属性name并没有重写(覆盖)父类的同名属性,这样当你访问
public static void Method(Token t)
{
Console.WriteLine(t.name());
}
的时候这个name就是Token 类的name属性,而不是IdentifierToken的,要返回为Variale请改IdentifierToken 中对属性name的定义为:
new public virtual string name()
{

return IdenToken;

}
或是new public string name()
{
return IdenToken;

}
hc_z 2003-11-20
  • 打赏
  • 举报
回复
学习
brightheroes 2003-11-20
  • 打赏
  • 举报
回复

jerryfangsh 2003-11-20
  • 打赏
  • 举报
回复
1、你在Token中定义了private string test;
2、你在IdentifierToken中定义了private string IdenToken;
3、由于以上两个步骤你定义的都是私有变量,因此当修改子类的变量时,你不会修改父类的变量;

但是以上并不是主要原因,更主要的是:
IdentifierToken variable = new IdentifierToken("Variale");
虽然是生成了一个IdentifierToken的对象,但是,同时通过base()调用了父类的构造函数,当把IdentifierToken对象传入Method函数时,进行了转换,即转换为了父类Token。因此此时当调用name()属性时,调用的就是Token的了。

你这样的设计是有问题的。
如果你坚持你这样的设计,那么你可以做如下的修改:

1、修改或增加Token的构造函数:
public Token()
{
test = "Hello world";
}
public Token(string test)
{
test = test;
}
2、修改IdentifierToken的构造函数
public IdentifierToken(string Iden) :base(Iden)
{
IdenToken = Iden;
}
这样就可以修改Token的test的值了。
当然,这并非是最好的设计。
gOODiDEA 2003-11-20
  • 打赏
  • 举报
回复
public virtual string name()
{

return IdenToken;

}
==》

public override string name()
kikill 2003-11-20
  • 打赏
  • 举报
回复
小弟有几点看法:
1。shanyou同志的这个程序很好的说明了方法的重写与隐藏问题。程序中,派生类IdentifierToken的name方法将她的基类的同名(相同签名)方法隐藏了(不是重写)
然而,在Method方法中,程序又将IdentifierToken的对象转换成其基类Token的对象,
这样,当调用参数t的name方法时,将会按照变量t的类型判断将调用哪个类的name方法,
而不是根据变量t所引用的对象的实际类型来调用(这里t所引用的对象是IdentifierToken
的对象variable)。所以就造成了输出"Hello world"的
结果。
2。解决这个问题又很多方法,比如象大家说的那样,将virtual 该成override 。但是象
jerryfangsh(碎片) 的方法有点复杂,而且很危险,因为,他(她)是通过改变Token类中
私有变量test的方法,来改变输出,而且这好象和我们讨论的多态没什么关系。他(她)
还有一个笔误:
public Token(string test)
{
test = test;
}

=》 public Token(string test)
{
this.test = test;
}


110,538

社区成员

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

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

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