Чтение онлайн

ЖАНРЫ

Язык программирования C#9 и платформа .NET5
Шрифт:

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;

else

salesBonus = 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
класса
Employee
объявлен виртуальным:

public 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
в похожей манере, выводя на консоль количество продаж):

// Manager.cs

public override void DisplayStats

{

base.DisplayStats;

// Вывод количества фондовых опционов

Console.WriteLine("Number of Stock Options: {0}", StockOptions);

}

// SalesPerson.cs

public override void DisplayStats

{

base.DisplayStats;

// Вывод количества продаж

Console.WriteLine("Number of Sales: {0}", SalesNumber);

}

Теперь,

когда каждый подкласс может истолковывать эти виртуальные методы значащим для него образом, их экземпляры ведут себя как более независимые сущности:

Console.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;

Вот результат тестового запуска приложения в его текущем виде:

***** The Employee Class Hierarchy *****

Name: Chucky

ID: 92

Age: 50

Pay: 100300

SSN: 333-23-2322

Number of Stock Options: 9337

Name: Fran

ID: 93

Age: 43

Pay: 5000

SSN: 932-32-3232

Number of Sales: 31

Переопределение виртуальных членов с помощью Visual Studio/Visual Studio Code

Вы наверняка заметили, что при переопределении члена класса приходится вспоминать тип каждого параметра, не говоря уже об имени метода и соглашениях по передаче параметров (

ref
,
out
и
params
). В Visual Studio и Visual Studio Code доступно полезное средство
IntelliSense
, к которому можно обращаться при переопределении виртуального члена. Если вы наберете слово
override
внутри области действия типа класса (и затем нажмете клавишу пробела), то
IntelliSense
автоматически отобразит список всех допускающих переопределение членов родительского класса, исключая уже переопределенные методы.

Если вы выберете член и нажмете клавишу <Enter>, то IDE-среда отреагирует автоматическим заполнением заглушки метода. Обратите внимание, что вы также получаете оператор кода, который вызывает родительскую версию виртуального члена (можете удалить эту строку, если она не нужна). Например, при использовании описанного приема для переопределения метода

DisplayStats
вы обнаружите следующий автоматически сгенерированный код:

public override void DisplayStats

{

base.DisplayStats;

}

Запечатывание виртуальных членов

Вспомните, что к типу класса можно применить ключевое слово

sealed
, чтобы предотвратить расширение его поведения другими типами через наследование. Ранее класс
PtSalesPerson
был запечатан на основе предположения о том, что разработчикам не имеет смысла дальше расширять эту линию наследования.

Поделиться с друзьями: