Вызов базового абстрактного метода при переопределении этого метода

#c#

#c#

Вопрос:

Если у меня есть следующее:

например

 public abstract class ClassA
{
     protected abstract void ValidateTransaction();
}

public abstract class ClassB : ClassA
{
     protected override void ValidateTransaction()
     {
          // some custom logic here
     }
}

public class ClassC : ClassB
{
     protected override void ValidateTransaction()
     {
          base.ValidateTransaction();
          // some additional custom logic here
     }
}
  

Итак, я не нашел обычаев в ClassC ValidateTransaction.Я не вижу, чтобы он где-либо вызывался.

Итак, я думаю, как это работает? Я имею в виду, что здесь вызывается метод в верхней части стека (вызывает метод переопределения ClassB, а затем включает логику в переопределение метода ClassB моим ClassC?)

Для меня это не имеет смысла, почему или как это работает, или намерение здесь.

ОБНОВЛЕНО

Хорошо, итак, я нашел место, где метод PerformTransaction() ClassA вызывается из множества подклассов в нашем проекте.

Итак, ClassA теперь выглядит так, с более подробной информацией для вас здесь:

 public abstract class ClassA
{
     public void PerformTransaction()
     {
           ValidateTransaction();
           // and calls some other code here.
     }

     protected abstract void ValidateTransaction();
}
  

Хорошо, тогда у нас все еще есть:

 public abstract class ClassB : ClassA
{
     protected override void ValidateTransaction()
     {
          // some custom logic here
     }
}

public class ClassC : ClassB
{
     protected override void ValidateTransaction()
     {
          base.ValidateTransaction();
          // some additional custom logic here
     }
}


public class SomeAbritraryClass : ClassC
{
      ClassA.PerformTransaction();
      ...
 }
  

итак, ClassA.PerformTransaction() вызывается в некоторых классах, наследующих ClassC.

Ответ №1:

Ну, это вызывает переопределяющий метод ClassC … который, случается, вызывает реализацию ClassB. Это не «включает» логику реализации ClassB непосредственно в скомпилированный код ClassC или что-то подобное — это просто вызов другого метода.

Не совсем ясно, что вас смущает — поведение, замысел дизайна или то, что показывает вам Find Usages.

Обратите внимание, что, несмотря на вашу тему письма, вы не вызываете «базовый абстрактный метод» — вы вызываете реализацию этого метода. Компилятор знает, что ClassC является производным от ClassB, который предоставляет реализацию метода, поэтому он выполняет этот вызов явно. Вы не могли бы сделать то же самое из самого ClassB, потому что тогда base.ValidateTransaction действительно это было бы попыткой вызвать абстрактный базовый метод.

Забавный факт: несмотря на то, что это вызов виртуального метода, это вызов невиртуального метода: компилятор знает точную реализацию для использования и включает ее в вызов. Если бы это был виртуальный вызов, вы бы вернулись к реализации ClassC, поскольку это переопределяет его 🙂

Комментарии:

1. извини, Джон, я облажался в своем посте. Я не нахожу примеров использования ClassC. позвольте мне исправить мой первоначальный пост.

2. @CoffeeAddict: Но вас смущает «Поиск использований»? Имейте в виду, что ClassC.ValidateTransaction все еще может быть вызван следующим образом: ClassA x = new ClassC(); a.ValidateTransaction();

3. ах …. не думал об этом таким образом. Однако, взглянув на код еще раз… Теперь, когда я присмотрелся повнимательнее, я вижу единственное место, где вызывается этот метод, — это базовый класс. Он вызывает этот абстрактный подкласс, определенный в моем исходном абстрактном классе. Итак, в ClassA есть какой-то метод, который вызывает ValidateTransaction(). Так что, это должно просачиваться вниз?

4. @CoffeeAddict: Да — если вы вызываете PerformTransaction для экземпляра ClassC (во время выполнения; тип во время компиляции должен быть только ClassA), это, в свою очередь, вызовет ClassC.ValidationTransaction, который, в свою очередь, вызывает ClassB.ValidateTransaction.

5. снова смотрите обновления. На самом деле PerformTransaction вызывается из подкласса … того, который наследует ClassC. Извините, вы можете надрать мне яйца позже.

Ответ №2:

Когда вызывается переопределение класса C, оно сначала вызывает переопределение B и выполняет там некоторую логику, которая затем будет расширена логикой C.

Насколько я знаю, они могли бы работать с одними и теми же переменными, данными. Я не знаю, потому что у меня нет всех данных.

Ответ №3:

Итак, я думаю, как это работает? Я имею в виду, что здесь вызывается метод в верхней части стека (вызывает метод переопределения ClassB, а затем включает логику в переопределение метода ClassB моим ClassC?)

Да, в принципе, именно это и происходит. Когда вы вызываете ValidateTransaction экземпляр ClassC , выполняется этот метод. Затем он явно выполняет метод базового класса ( ClassB ), а затем добавляет свою собственную дополнительную проверку.

Вероятно, вы не нашли прямого использования ClassB.ValidateTransaction() , потому что нет экземпляров ClassB (определенных как ClassB ), для которых это вызывается. Однако любой ClassC вызов будет косвенно использовать ClassB.ValidateTransaction() через base.ValidateTransaction() строку.

Комментарии:

1. извините, я не нахожу примеров использования ClassC. позвольте мне исправить мой первоначальный пост.