C # Переопределение метода базового класса более чем одного производного класса в цепочке наследования - PullRequest
5 голосов
/ 23 ноября 2010

У меня есть цепочка наследования, которая состоит из трех классов A, B и C, где A и B являются абстрактными, а C является конкретной реализацией B.

У меня есть виртуальный метод в базовом абстрактном классе A, Foo(), который я хотел бы переопределить в конкретном классе C.

Если я пытаюсь переопределить только в классе C, он никогда не выбирается и всегда использует реализацию базового класса по умолчанию, но если я переопределяю оба B & C, он всегда использует только реализацию B.Foo() виртуального метода.

Должен ли я объявить что-то дополнительное в B.Foo (), кроме 'override'?

Очевидно, что это упрощенные версии моих классов, но вот мои объявления методов:

abstract class A {
  protected virtual string Foo() {
    return "A";
  }
}

abstract class B : A {
  protected override string Foo() {
    return "B";
  }
}

class C : B {
  protected override string Foo() {
    return "C";
  }
}

Ответы [ 2 ]

5 голосов
/ 23 ноября 2010

А?

void Main()
{
    new C().DumpFoo(); // C
    A x=new C();
    x.BaseDumpFoo(); //C
}

abstract class A {
  protected virtual string Foo() {
    return "A";
  }
  public void BaseDumpFoo()
  {
    Console.WriteLine(Foo());
  }
}

abstract class B : A {
  protected override string Foo() {
    return "B";
  }
}

class C : B {
  protected override string Foo() {
    return "C";
  }
  public void DumpFoo()
  {
    Console.WriteLine(Foo());
  }
}

Вывод C. Удалите Foo реализацию из B, и на выходе останется C

0 голосов
/ 23 ноября 2010

Проблема в том, что, поскольку B переопределяет метод, при вызове его из C он никогда не достигает его реализации в иерархии наследования.Вам нужно определить метод в B как новый (чтобы он переопределял реализацию из A) и определить его также как виртуальный (чтобы C мог использовать свою собственную реализацию, у вас будет что-то вроде

abstract class A
{
    protected virtual string Foo()
    {
        return "A";
    }
}

abstract class B : A
{
    protected new virtual string Foo()
    {
        return "B";
    }
}

class C : B
{
    protected override string Foo()
    {
        return "C";
    }
...