c# 关于多态性的问题

微风往事 2010-04-22 11:33:16
using System;

namespace 多态性_1
{
public class Person
{
private string name = "张三";
private int age = 26;
public Person(string Name, int Age)
{
name = Name;
age = Age;
}
protected virtual void Display()
{
Console.WriteLine("姓名:{0},年龄:{1}", name, age);
}
static public void DisplayData(Person aPerson)
{
aPerson.Display();
}
}
public class Employee:Person
{
private string department;
private decimal salary;
public Employee(string Name, int Age, string D, decimal S):base(Name, Age)
{
department = D;
salary = S;
}
protected override void Display()
{
base.Display();
Console.WriteLine("部门:{0},薪金:{1}", department , salary );
}
}
class Test
{
static void Main(string[] args)
{
Person OnePerson = new Person("李四", 40);
Person.DisplayData(OnePerson);
Employee OneEmployee = new Employee ("王五", 23, "客服部", 5000);
Person .DisplayData(OneEmployee);
Console.Read();
}
}
}

运行的结果是
姓名:李四,年龄:40
姓名:王五,年龄:23
部门:客服部,薪金:5000

为什么在Main()主函数中Person.DisplayData(OneEmployee);这句语句输出的是派生类重写后的输出的语句呢?
这里DisplayData是基类的静态方法!其中执行的语句是aPerson.Display();怎么这个Display却成了派生类重写后的内容了呢?
是不是只要派生类,做了实例化后,基类中的虚方法就被重写了,不然的话在上面的代码中,并没有用派生类的对象去调用重写的Display方法啊,怎么结果会成为这样呢?
...全文
256 28 打赏 收藏 转发到动态 举报
写回复
用AI写文章
28 条回复
切换为时间正序
请发表友善的回复…
发表回复
piaomiaogu007 2010-04-24
  • 打赏
  • 举报
回复
应为只要是重写了以后再次调用Display方法时,就会把子类的构造函数的内容覆盖父类输出
hy_yyf 2010-04-23
  • 打赏
  • 举报
回复
多态是看派生类是否有,若有就执行,若无,就执行基类的
fan7421436 2010-04-23
  • 打赏
  • 举报
回复
多态 应该是 先去基类里面需找执行 然后再到 派生类 里面需找执行
sxiaohui8709253 2010-04-23
  • 打赏
  • 举报
回复
学习 接分
微风往事 2010-04-23
  • 打赏
  • 举报
回复
当我在Person .DisplayData (OneEmployee);这句设置断点时
执行到aPerson.Display();这句时,下一句就跳到了
protected override void Display()
{ base.Display();
Console.WriteLine("部门:{0},薪金:{1}", department , salary );
}
这一部分呢?为什么不去执行基类中的
protected virtual void Display()
{ Console.WriteLine("姓名:{0},年龄:{1}", name, age); }
Joe-xXx 2010-04-23
  • 打赏
  • 举报
回复
Person.DisplayData(OnePerson);
==>姓名:李四,年龄:40

Person .DisplayData(OneEmployee);

==>姓名:王五,年龄:23
部门:客服部,薪金:5000

设置断点,单步调试就明白啦
gramaster 2010-04-23
  • 打赏
  • 举报
回复
楼主的问题牵涉到2个关键字:base和override。
override在子类中重写了基类的virtual方法,而这个重写的方法里又有base.Display,所以会调用基类的Display方法,基类Display方法的参数是:王五, 23。所以结果就这样了。
顺便多说一句,要是有多重继承的话,有BASE方法的话,那调用的方法应该是最高级父类的方法。
例如:
public class A
{
……
public virtual void M1()
{
……
}
public void M2()
{
……
}

……
}
public class B:A
{……
public override void M1()
{
base.M1();
……
}
……
}
public class C:B
{……
public override void M1()
{
base.M1();
base.M2();
……
}
……
}

B继承A,C继承B,B.M1显然是执行A中的M1,C.M1中因为继承了B.M1所以会执行B.M1而不是A.M1,而BASE.M2因为B中没有M2方法所以再去B的父类中找到了A.M2执行。

xcf007 2010-04-23
  • 打赏
  • 举报
回复
这一部分呢?为什么不去执行基类中的
protected virtual void Display()
你没看到那个virtual啊?

你去掉virtual和override就会调用了

flyerwing 2010-04-23
  • 打赏
  • 举报
回复
C井多态分为:编译时多态和运行时多态;编译时多态可以从函数重载方面理解;运行时多态可以从泛型微观的理解,也可从函数重写理解吧。
没什么用。
gramaster 2010-04-23
  • 打赏
  • 举报
回复
楼上的朋友,这个问题的关键不是你说那个啊,其实是BASE啊。即使子类重写了基类的方法。你看这个
2.1 base关键字

其用于在派生类中实现对基类公有或者受保护成员的访问,但是只局限在构造函数、实例方法和实例属性访问器中,MSDN中小结的具体功能包括:

调用基类上已被其他方法重写的方法。
指定创建派生类实例时应调用的基类构造函数。

也就是说,其实还是调用了基类的Display方法。只不过因为传递到基类的参数是:王五, 23。
b3366450 2010-04-23
  • 打赏
  • 举报
回复
先顶在看!嘿嘿 ···············
liuyileneal 2010-04-23
  • 打赏
  • 举报
回复
你的子类已经继承了DisplayData这个方法
Person .DisplayData(OneEmployee);
在这你传入了一个子类对象,
static public void DisplayData(Person aPerson)
{
aPerson.Display();
}
这个地方用父类的引用接收,相当于这样了
Person aPerson = new Employee("王五", 23, "客服部", 5000);
然后调用方法
aPerson.Display();
它实际上是子类对象,并且子类重写了display方法,所以就会调用子类重写的方法
gramaster 2010-04-23
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 peter200694013 的回复:]
多态-〉 调用方法时会根据实际的对象类型调用相应的方法。
Person .DisplayData (OneEmployee);
这个方法的参数类型是Person,所以可以接受的参数是Person和它的子类。当在方法中执行
person.Display()时,会根据person的实际类型去调用。因为是Employee类型,且Display方法是override,所以调用的是Employee的d……
[/Quote]
是调用的子类中重写过的Display方法,但是子类的Display方法中有个base.Display();还是要调用基类的,但是这个基类的参数name, age是用的子类实例OneEmployee的参数:王五,23
Peter200694013 2010-04-23
  • 打赏
  • 举报
回复
如果你把Person中的Display前的virtual去掉,然后在Employee的Display前的override换成new。这样再执行的话,调用时应该是执行的是Person的Display方法了
//因为使用new的话是隐藏了基类的方法
Peter200694013 2010-04-23
  • 打赏
  • 举报
回复
多态-〉 调用方法时会根据实际的对象类型调用相应的方法。
Person .DisplayData (OneEmployee);
这个方法的参数类型是Person,所以可以接受的参数是Person和它的子类。当在方法中执行
person.Display()时,会根据person的实际类型去调用。因为是Employee类型,且Display方法是override,所以调用的是Employee的display方法
gramaster 2010-04-23
  • 打赏
  • 举报
回复
最近在看理论书,看到《你必须知道的.net》里这么说的,结合示例才搞明白这些,自己以前没系统学习理论都是从代码学的。
gramaster 2010-04-23
  • 打赏
  • 举报
回复
Person .DisplayData(OneEmployee);这句
以OneEmployee为参数执行static public void DisplayData(Person aPerson)
{
aPerson.Display();
}
这句就到执行protected override void Display()
{
base.Display();
Console.WriteLine("部门:{0},薪金:{1}", department , salary );
}
到了这里,注意是base.Display();是执行基类的 Display方法,也就是protected virtual void Display()
{ Console.WriteLine("姓名:{0},年龄:{1}", name, age); }
这里是关键了,这句的参数name, age,因为是以OneEmployee为参数,OneEmployee里有这句public Employee(string Name, int Age, string D, decimal S):base(Name, Age)
{
department = D;
salary = S;
}
注意这个:base(Name, Age) //派生类和基类通信,以base实现,基类首先被调用,所以其实
基类的public Person(string Name, int Age)
{
name = Name;
age = Age;
}
因为参数是:王五,23。所以base.Display();执行基类的protected virtual void Display()
{
Console.WriteLine("姓名:{0},年龄:{1}", name, age);
}
结果就是:姓名:王五,年龄:23 了
然后才是子类的Console.WriteLine("部门:{0},薪金:{1}", department , salary );
sunfu4359 2010-04-23
  • 打赏
  • 举报
回复
路过,学习了`~~顶顶
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 lius320 的回复:]
当我在Person .DisplayData (OneEmployee);这句设置断点时
执行到aPerson.Display();这句时,下一句就跳到了
protected override void Display()
{ base.Display();
Console.WriteLine("部门:{0},薪金:{1}", department , salary );
}
……
[/Quote]

就是不去执行才对。
  • 打赏
  • 举报
回复
不要看到了那行代码就以为 aPerson 一定只能是Person。如果不理解 aPerson 也可以是Person任何子类,那么就不理解多态。
加载更多回复(7)

110,499

社区成员

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

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

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