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

ЖАНРЫ

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

Вам уже известно, что повторное использование кода встречается в двух видах. Только что было продемонстрировано классическое отношение "является". Перед тем, как мы начнем исследование третьего принципа ООП (полиморфизма), давайте взглянем на отношение "имеет" (также известное как модель включения/делегации или агрегация). Возвратитесь к проекту

Employees
и создайте новый файл по имени
BenefitPackage.cs
. Поместите в него следующий код, моделирующий пакет льгот для сотрудников:

namespace Employees

{

//
Этот новый тип будет функционировать как включаемый класс.

class BenefitPackage

{

// Предположим, что есть другие члены, представляющие

// медицинские/стоматологические программы и т.п.

public double ComputePayDeduction

{

return 125.0;

}

}

}

Очевидно, что было бы довольно странно устанавливать отношение "является" между классом

BenefitPackage
и типами сотрудников. (Разве сотрудник "является" пакетом льгот? Вряд ли.) Однако должно быть ясно, что какое-то отношение между ними должно быть установлено. Короче говоря, нужно выразить идею о том, что каждый сотрудник "имеет" пакет льгот. Для этого можно модифицировать определение класса
Employee
следующим образом:

// Теперь сотрудники имеют льготы.

partial class Employee

{

// Contain a BenefitPackage object.

protected BenefitPackage EmpBenefits = new BenefitPackage;

...

}

На данной стадии вы имеете объект, который благополучно содержит в себе другой объект. Тем не менее, открытие доступа к функциональности содержащегося объекта внешнему миру требует делегации. Делегация — просто действие по добавлению во включающий класс открытых членов, которые работают с функциональностью содержащегося внутри объекта.

Например, вы могли бы изменить класс

Employee
так, чтобы он открывал доступ к включенному объекту
EmpBenefits
с применением специального свойства, а также использовать его функциональность внутренне посредством нового метода по имени
GetBenefitCost
:

partial class Employee

{

// Содержит объект BenefitPackage.

protected BenefitPackage EmpBenefits = new BenefitPackage;

// Открывает доступ к некоторому поведению, связанному со льготами.

public double GetBenefitCost

=> EmpBenefits.ComputePayDeduction;

// Открывает доступ к объекту через специальное свойство.

public BenefitPackage Benefits

{

get { return EmpBenefits; }

set { EmpBenefits = value; }

}

}

В

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

Console.WriteLine("***** The Employee Class Hierarchy *****\n");

...

Manager chucky = new Manager("Chucky", 50, 92, 100000, "333-23-2322", 9000);

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;

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