Литмир - Электронная Библиотека
A
A

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
теперь вложено непосредственно в класс
Employee
:

partial 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;

138
{"b":"847442","o":1}