Язык программирования C#9 и платформа .NET5
...}Поскольку метод
был определен с ключевым словомGiveBonus(), бонусы можно раздавать продавцам и менеджерам (а также продавцам с частичной занятостью):publicConsole.WriteLine("***** The Employee Class Hierarchy *****\n");// Выдать каждому сотруднику бонус?Manager chucky = new Manager("Chucky", 50, 92, 100000, "333-23-2322", 9000);chucky.GiveBonus(300);chucky.DisplayStats();Console.WriteLine();SalesPerson fran = new SalesPerson("Fran", 43, 93, 3000, "932-32-3232", 31);fran.GiveBonus(200);fran.DisplayStats();Console.ReadLine();Проблема с текущим проектным решением заключается в том, что открыто унаследованный метод
функционирует идентично для всех подклассов. В идеале при подсчете бонуса для штатного продавца и частично занятого продавца должно приниматься во внимание количество продаж. Возможно, менеджеры вместе с денежным вознаграждением должны получать дополнительные фондовые опционы. Учитывая это, вы однажды столкнетесь с интересным вопросом: "Как сделать так, чтобы связанные типы реагировали по-разному на один и тот же запрос?". Попробуем найти на него ответ.GiveBonus()Использование ключевых слов virtual и override
Полиморфизм предоставляет подклассу способ определения собственной версии метода, определенного в его базовом классе, с применением процесса, который называется переопределением метода. Чтобы модернизировать текущее проектное решение, необходимо понимать смысл ключевых слов
иvirtual. Если базовый класс желает определить метод, который может быть (но не обязательно) переопределен в подклассе, то он должен пометить его ключевым словомoverride:virtualpartial class Employee{// Теперь этот метод может быть переопределен в производном классе.public virtual void GiveBonus(float amount){Pay += amount;}...}На заметку! Методы, помеченные ключевым словом
, называются виртуальными методами.virtualКогда подкласс желает изменить реализацию деталей виртуального метода, он прибегает к помощи ключевого слова
. Например, классыoverrideиSalesPersonмогли бы переопределять методManager, как показано ниже (предположим, что классGiveBonus()не будет переопределятьPtSalesPerson, а потому просто наследует его версию изGiveBonus()):SalesPersonusing System;class SalesPerson : Employee{...// Бонус продавца зависит от количества продаж.public override void GiveBonus(float amount){int salesBonus = 0;if (SalesNumber >= 0 && SalesNumber <= 100)salesBonus = 10;else{if (SalesNumber >= 101 && SalesNumber <= 200)salesBonus = 15;elsesalesBonus = 20;}base.GiveBonus(amount * salesBonus);}}class Manager : Employee{...public override void GiveBonus(float amount){base.GiveBonus(amount);Random r = new Random();StockOptions += r.Next(500);}}Обратите внимание, что каждый переопределенный метод может задействовать стандартное поведение посредством ключевого слова
.baseТаким образом, полностью повторять реализацию логики метода
вовсе не обязательно, а взамен можно повторно использовать (и расширять) стандартное поведение родительского класса.GiveBonus()Также предположим, что текущий метод
классаDisplayStats()объявлен виртуальным:Employeepublic virtual void DisplayStats(){Console.WriteLine("Name: {0}", Name);Console.WriteLine("Id: {0}", Id);Console.WriteLine("Age: {0}", Age);Console.WriteLine("Pay: {0}", Pay);Console.WriteLine("SSN: {0}", SocialSecurityNumber);}Тогда каждый подкласс может переопределять метод
с целью отображения количества продаж (для продавцов) и текущих фондовых опционов (для менеджеров). Например, рассмотрим версию методаDisplayStats()из классаDisplayStats()(классManagerреализовывал бы методSalesPersonв похожей манере, выводя на консоль количество продаж):DisplayStats()