3

我有一个问题(这是我的错,我只是无法发现我做错了什么)“ToString”没有调用正确的方法......

public class ClassA
{
   public override ToString()
   {
      return "Hello, I'm class A.";
   }
}

public class ClassB : ClassA
{
   public override ToString()
   {
       return "Hello, I'm class B.";
   }
}

ClassB myClassB = new ClassB();
List<ClassA> myClassAList = new List<ClassA>();

myClassAList.Add((ClassA) myClassB);
ClassA tempClassA = myClassAList[0];
Console.WriteLine(tempClassA.ToString());

我从“ClassB”而不是“ClassA”得到“ToString”我做错了什么?

4

4 回答 4

6

你没有做错任何事——这就是多态虚拟方法的工作方式。当您将 ClassB 放入 ClassA 引用的集合时,它仍然是 ClassB 对象。如果对象确实属于 ClassB,则调用 .ToString() 将始终找到 ClassB.ToString()。

于 2009-03-30T16:17:00.780 回答
4

您在 ClassB 中覆盖 ToString 而不是将其隐藏在原始方法中,这将导致被覆盖的方法优先。你能做的是..

public class ClassA
{
    public override string ToString()
    {
        return "Hello, I'm class A.";
    }
}

public class ClassB : ClassA
{
    public new string ToString()
    {
        return "Hello, I'm class B.";
    }
}

...

List<ClassA> theList = new List<ClassA>
{
    (ClassA)new ClassB(),
    (ClassA)new ClassB()
};

ClassA a = theList[0];
Console.WriteLine(a.ToString());

// OR... 

Console.WriteLine(new ClassA().ToString());  // I'm Class A
Console.WriteLine(new ClassB().ToString());  // I'm Class B
Console.WriteLine(((ClassA)new ClassB()).ToString()); // I'm Class A
于 2009-03-30T16:18:23.117 回答
0

ToString 是一个虚拟方法,变量的类型是什么并不重要,实际对象的类型是什么很重要。

如果该方法不是虚拟的,则调用将转到编译器将知道的方法,即 ClassA ToString 方法。

虚拟方法通过查找表实现,绑定到对象类型。由于变量“tempClassA”中的对象实际上是 ClassB 类型的对象,因此使用 ClassB 的查找表,因此使用该类的 ToString 方法。

于 2009-03-30T16:16:30.080 回答
0

你得到了正确的结果。您将 ClassB 的一个实例添加到您的列表中;即使您将其视为ClassA。因此,调用虚拟ToString方法时,会导致调用ClassB的ToString;因为那是您正在使用的实际对象。

于 2009-03-30T16:18:49.810 回答