многоуровневое наследование в C # без ключевого слова virtual - PullRequest
0 голосов
/ 23 мая 2019

Я новичок в C #, просто вопрос о многоуровневом наследовании Допустим, у нас есть следующие классы:

Class Employee
{
   public virtual void CalculateBonus() {
      ...
   }
}

class SalesPerson : Employee 
{
    public override void CalculateBonus() {
      ...
   }
}

допустим, у нас есть другой класс, производный от SalesPerson

class PTSalesPerson : SalesPerson
{
   public override void CalculateBonus() {
      ...
   }
}

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

class SalesPerson : Employee 
{
   public virtual override void CalculateBonus() {
     ... //compiler error
   }
}

, чтобы PTSalesPerson мог переопределить свой родительский метод. значит ли это, что ключевое слово «virtual» должно появляться только в базовом классе уровня 1? или переопределить = переопределить + виртуальный?

Ответы [ 2 ]

7 голосов
/ 23 мая 2019

Вы не можете пометить переопределенный метод как virtual, так как он по определению уже виртуальный

виртуальный (C # Reference)

Примечания

Когда вызывается виртуальный метод, тип объекта во время выполнения проверено на переопределение члена. Главный член в большинстве вызывается производный класс, который может быть исходным членом, если нет производный класс переопределил член.

По умолчанию методы не виртуальные. Вы не можете переопределить не виртуальный способ.

Нельзя использовать виртуальный модификатор с модификаторами static, abstract, private или override.


Если вы это сделаете, вы получите неприятную ошибку времени компиляции

Ошибка компилятора CS0113

Элемент 'function', помеченный как переопределенный, не может быть помечен как новый или виртуальный

Это взаимоисключающие, чтобы пометить метод с новым и переопределить ключевые слова.


Чтобы ответить на основную проблему, вы отмечаете самый низкий уровень, который должен быть переопределен с virtual, любой производный класс затем может override it

0 голосов
/ 23 мая 2019

Ключевое слово VIRTUAL означает, что ЛЮБОЙ класс дочернего уровня МОЖЕТ переопределить данную функцию.

Таким образом, если ни у одного из дочерних классов нет декларации переопределения функции, они все еще будут иметь эту функцию,он просто перейдет к самому верхнему классу сотрудников.

Если, например, вы сделали переопределение только для класса PTSalesPerson, то только класс THAT будет иметь другую функциональность ... Employee и SalesPersonвсе еще работайте с объявлением уровня «Сотрудник» функции / метода.

Помогает ли это вам уточнить?

Как только любой метод объявлен как виртуальный в его родительской иерархии, любой дочерний элемент ВСЕГДА будетВОЗМОЖНО ПЕРЕГРУЗИТЬ от своего родителя независимо от уровня.Но также допустим, что у вас есть уровень иерархии

Class1
  Class2 : Class1
    Class3 : Class2
      Class4 : Class3

, и вы объявляете переопределение в Class3 ... Экземпляр Class4 будет работать на основе родительского элемента IT, который является реализацией вызова метода Class3, а не объявлением Class1.

Теперь, если вы хотите сделать комбинацию, вы всегда можете вызвать базовый метод, а затем сделать больше.

Пример:

Class Employee
{
   public decimal MyBonus = 0.0m;
   public virtual void CalculateBonus() 
   {
      MyBonus = MySales * .13m;
   }
}

class SalesPerson : Employee 
{
}

class PTSalesPerson : SalesPerson
{
   public override void CalculateBonus() 
   {
      // go do the NORMAL Calculation at the EMPLOYEE Level
      base.CalculateBonus();
      // Now continue from that... As Part-Time sales person,
      // they get 1/4 of that rate.  So take whatever the result
      // WAS and multiply by .25
      MyBonus = MyBonus * .25m;
   }
}

Уточнениепри вызове цепочки методов

Согласно вашему комментарию / вопросу, метод, который PTSalesPerson будет переопределять, будет Employees, потому что это следующий объявленный метод в цепочке ... Для теста создайте свои собственные классыкак выше и просто сделать MessageBox.Show («что-то») и посмотреть, что происходит на каждом.Если бы у класса SalesPerson был объявленный метод, то THAT был бы переопределенным, но также вызывался бы «base.CalculateBonus».

Подумайте о «базе».как семейная иерархия.Ты ребенок для своих родителей ... Великий ребенок для своих бабушек и дедушек.Итак, ваша «база».был бы вашим прямым родителем.

ДОПОЛНИТЕЛЬНАЯ ТОЧКА при наследовании

Единственное предупреждение, которое я не раскрыл (спасибо Servy), это объявление расширенных классов, где класс помечен какзапечатанный.Запечатанные классы в основном блокируют класс, поэтому никакие дополнительные производные классы не могут быть выполнены против него.И это применимо ко всему классу ... свойства, методы, функциональность и т. Д.

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