Язык программирования C#9 и платформа .NET5
double cost = chucky.GetBenefitCost();Console.WriteLine($"Benefit Cost: {cost}");Console.ReadLine();Определения вложенных типов
В главе 5 кратко упоминалась концепция вложенных типов, которая является развитием рассмотренного выше отношения "имеет". В C# (а также в других языках .NET) допускается определять тип (перечисление, класс, интерфейс, структуру или делегат) прямо внутри области действия класса либо структуры. В таком случае вложенный (или "внутренний") тип считается членом охватывающего (или "внешнего") типа, и в глазах исполняющей системы им можно манипулировать как любым другим членом (полем, свойством, методом и событием). Синтаксис, применяемый для вложения типа, достаточно прост:
public class OuterClass{// Открытый вложенный тип может использоваться кем угодно.public class PublicInnerClass {}// Закрытый вложенный тип может использоваться.// только членами включающего классаprivate class PrivateInnerClass {}}Хотя синтаксис довольно ясен, ситуации, в которых это может понадобиться, не настолько очевидны. Для того чтобы понять данный прием, рассмотрим характерные черты вложенных типов.
• Вложенные типы позволяют получить полный контроль над уровнем доступа внутреннего типа, потому что они могут быть объявлены как закрытые (вспомните, что невложенные классы нельзя объявлять с ключевым словом
).private• Поскольку вложенный тип является членом включающего класса, он может иметь доступ к закрытым членам этого включающего класса.
• Часто вложенный тип полезен только как вспомогательный для внешнего класса и не предназначен для использования во внешнем мире.
Когда тип включает в себя другой тип класса, он может создавать переменные-члены этого типа, как в случае любого другого элемента данных. Однако если с вложенным типом нужно работать за пределами включающего типа, тогда его придется уточнять именем включающего типа. Взгляните на приведенный ниже код:
// Создать и использовать объект открытого вложенного класса. Нормально!OuterClass.PublicInnerClass inner;inner = new OuterClass.PublicInnerClass();// Ошибка на этапе компиляции! Доступ к закрытому вложенному// классу невозможен!OuterClass.PrivateInnerClass inner2;inner2 = new OuterClass.PrivateInnerClass();Для применения такой концепции в примере с сотрудниками предположим, что определение
теперь вложено непосредственно в классBenefitPackage:Employeepartial class Employee{public class BenefitPackage{// Предположим, что есть другие члены, представляющие// медицинские/стоматологические программы и т.д.public double ComputePayDeduction(){return 125.0;}}...}Процесс вложения может распространяться настолько "глубоко", насколько требуется. Например, пусть необходимо создать перечисление по имени
, документирующее разнообразные уровни льгот, которые может выбирать сотрудник. Чтобы программно обеспечить тесную связь между типамиBenefitPackageLevel,EmployeeиBenefitPackage, перечисление можно вложить следующим образом:BenefitPackageLevel// В класс Employee вложен класс BenefitPackage.public partial class Employee{// В класс BenefitPackage вложено перечисление BenefitPackageLevel.public class BenefitPackage{public enum BenefitPackageLevel{Standard, Gold, Platinum}public double ComputePayDeduction(){return 125.0;}}...}Вот как приходится использовать перечисление
из-за отношений вложения:BenefitPackageLevel...// Определить уровень льгот.Employee.BenefitPackage.BenefitPackageLevel myBenefitLevel =Employee.BenefitPackage.BenefitPackageLevel.Platinum;Итак, к настоящему моменту вы ознакомились с несколькими ключевыми словами (и концепциями), которые позволяют строить иерархии типов, связанных посредством классического наследования, включения и вложения. Не беспокойтесь, если пока еще не все детали ясны. На протяжении оставшихся глав книги будет построено немало иерархий. А теперь давайте перейдем к исследованию последнего принципа ООП — полиморфизма.
Третий принцип объектно-ориентированного программирования: поддержка полиморфизма в C#
Вспомните, что в базовом классе
определен метод по имениEmployee, который первоначально был реализован так (до его обновления с целью использования шаблона свойств):GiveBonus()public partial class Employee{public void GiveBonus(float amount) => _currPay += amount;