本帖最后由 lius320 于 2010-04-22 23:33:51 编辑

解决方案 »

  1.   


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

    以上信息是
    Person .DisplayData(OneEmployee);
    所以打印出来的
    因为你用的父类对象来调的方法,而参数传的却是子类的
    又因为DisplayData方法是重写的,所以它会先调用自己的,随后再是子类重写后的方法
      

  2.   

    DisplayData方法是重写的,怎么会是重写的? 它不是个静态的方法吗?而且其中的aPerson.Display();
    也是基类的对象啊!
      

  3.   

    Person.DisplayData(OnePerson); 
    ==>姓名:李四,年龄:40Person .DisplayData(OneEmployee);==>姓名:王五,年龄:23
       部门:客服部,薪金:5000设置断点,单步调试就明白啦
      

  4.   

    当我在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);    }   
      

  5.   

    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 );
     
      

  6.   

    最近在看理论书,看到《你必须知道的.net》里这么说的,结合示例才搞明白这些,自己以前没系统学习理论都是从代码学的。
      

  7.   

    多态-〉 调用方法时会根据实际的对象类型调用相应的方法。
    Person .DisplayData (OneEmployee);
    这个方法的参数类型是Person,所以可以接受的参数是Person和它的子类。当在方法中执行
    person.Display()时,会根据person的实际类型去调用。因为是Employee类型,且Display方法是override,所以调用的是Employee的display方法
      

  8.   

    如果你把Person中的Display前的virtual去掉,然后在Employee的Display前的override换成new。这样再执行的话,调用时应该是执行的是Person的Display方法了
    //因为使用new的话是隐藏了基类的方法
      

  9.   

    是调用的子类中重写过的Display方法,但是子类的Display方法中有个base.Display();还是要调用基类的,但是这个基类的参数name, age是用的子类实例OneEmployee的参数:王五,23 
      

  10.   

    你的子类已经继承了DisplayData这个方法
      Person .DisplayData(OneEmployee);
    在这你传入了一个子类对象,
     static public void DisplayData(Person aPerson)     
                { 
                    aPerson.Display();
                }    
    这个地方用父类的引用接收,相当于这样了
    Person aPerson = new Employee("王五", 23, "客服部", 5000);
    然后调用方法
    aPerson.Display();
    它实际上是子类对象,并且子类重写了display方法,所以就会调用子类重写的方法
      

  11.   

    楼上的朋友,这个问题的关键不是你说那个啊,其实是BASE啊。即使子类重写了基类的方法。你看这个
    2.1 base关键字其用于在派生类中实现对基类公有或者受保护成员的访问,但是只局限在构造函数、实例方法和实例属性访问器中,MSDN中小结的具体功能包括:调用基类上已被其他方法重写的方法。 
    指定创建派生类实例时应调用的基类构造函数。也就是说,其实还是调用了基类的Display方法。只不过因为传递到基类的参数是:王五, 23。
      

  12.   

    这一部分呢?为什么不去执行基类中的
    protected virtual void Display()
    你没看到那个virtual啊?你去掉virtual和override就会调用了
      

  13.   

    楼主的问题牵涉到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执行。
      

  14.   

    兄弟,我只说一句。
    没有老爸那有儿子!
    Employee是Person的儿子。Employee  OneEmployee = new Employee ("王五", 23, "客服部", 5000);
    Person .DisplayData(OneEmployee);
    这个DisplayData你重写了,他肯定先去找老爸的方法、再找自己的方法
      

  15.   

    在main函数处打上断点,按F11,自己看吧!
    多看几遍就明白了。
      

  16.   

    构造函数public  Employee(string Name, int Age, string D, decimal S):base(Name, Age)
    的执行过程,一定是。爷爷,爸爸,自己
      

  17.   

    在第二次执行        static public void DisplayData(Person aPerson)     
                { 
                    aPerson.Display();
                }  时,这个Person此时实际上是(被实例化时是)一个Employee,因此Display是去执行这个Employee的Display,这是面向对象技术公认的规则。面向对象技术的基本规则是脱离语言实现的。各种语言实现机制不同,例如(过去的)c++与.net对继承的实现就完全不同,但是它们要实现的效果必须相同,必须符合面向对象的公认规则。例如过去c++的书上可能会告诉你Emplyoee对象内部有一个private的指针指向一个Person类型的对象,但是.net根本不是这样实现继承的。如果你抱着底层结构的角度去看面向对象设计,永远也看不明白。只有抛开语言具体的实现,才能看明白如何进行面向对象设计。
      

  18.   

    不要看到了那行代码就以为 aPerson 一定只能是Person。如果不理解 aPerson 也可以是Person任何子类,那么就不理解多态。
      

  19.   

    应为只要是重写了以后再次调用Display方法时,就会把子类的构造函数的内容覆盖父类输出