C# ToString继承

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”中获取了“ToString”,而不是“ClassA”,我做错了什么?

多个拼写错误:“pulbic”,“retutn”,“pulbic” - abelenky
4个回答

6

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


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

这并不会改变任何事情。你不能在这里违反ClassA的接口契约。 - Konrad Rudolph
1
如果你通过 new 隐藏 ToString 方法,然后将 ClassB 向下转换为 ClassA 并调用 ToString() 方法,那么你将得到 ClassA 的重写 ToString 方法。尝试一下 Console.WriteLine(((ClassA)new ClassB()).ToString()); - Quintin Robinson
我将发布我用于测试的代码,它对我来说似乎是有效的,但我真诚地想知道我做错了什么。 - Quintin Robinson
我会去吃粪。我忘了在ClassA中使用“override”,于是Mono解释器(正确地?)认为根本没有覆盖ToString,所以我的输出仅为ClassB(即GetType().ToString())。 - Konrad Rudolph
我觉得你不用太担心,当你说它没起作用时,我真的以为我做错了什么。据我所知,如果你没有指定new或overrides中的任何一个,那么生成的输出结果与指定new相同,但IDE会给出编译器警告。 - Quintin Robinson

0

ToString是一个虚方法,它不关心你的变量类型是什么,而是关心实际对象的类型。

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

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


0

你得到了正确的结果。你将ClassB的一个实例添加到了列表中,尽管你将其视为ClassA。因此,当你调用虚拟ToString方法时,它将导致调用ClassB的ToString方法;因为这是你正在处理的实际对象类型。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接