C # ToString наследование - PullRequest
       12

C # ToString наследование

3 голосов
/ 30 марта 2009

У меня проблема (это моя вина, я просто не могу определить, что я делаю неправильно), когда 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());

Я получаю "ToString" от "ClassB", а не "ClassA", что я делаю не так?

Ответы [ 4 ]

6 голосов
/ 30 марта 2009

Вы не делаете ничего плохого - так работают виртуальные методы полиморфизма. Когда вы помещаете ClassB в коллекцию ссылок ClassA, это все еще объект ClassB. Вызов .ToString () всегда найдет ClassB.ToString (), если объект действительно принадлежит ClassB.

4 голосов
/ 30 марта 2009

Вы переопределяете ToString в ClassB вместо того, чтобы скрывать его от оригинала, что приведет к тому, что переопределенный метод будет иметь приоритет. Что вы могли бы сделать, это ..

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
0 голосов
/ 30 марта 2009

Вы получаете правильные результаты. Вы добавляете экземпляр ClassB в свой список; даже если вы относитесь к нему как к ClassA. Поэтому, когда вы вызываете виртуальный метод ToString, это приведет к вызову ToString класса B; потому что это фактический тип объекта, с которым вы работаете.

0 голосов
/ 30 марта 2009

ToString - это виртуальный метод, не имеет значения, какой тип вашей переменной, имеет значение тип реального объекта.

Если бы метод не был виртуальным, вызов перешел бы к методу, о котором должен знать компилятор, а именно к методу ClassA ToString.

Виртуальные методы реализуются через таблицу поиска, привязанную к типу объекта. Поскольку объект, в котором вы в конечном итоге находитесь в переменной «tempClassA», действительно является объектом типа ClassB, используется таблица поиска для ClassB, и, следовательно, для этого класса используется метод ToString.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...