В целях иллюстрации давайте инкапсулируем поле empName, для чего к существующему классу Employee необходимо добавить показанные ниже открытые методы. Обратите внимание, что метод SetName() выполняет проверку входных данных, чтобы удостовериться, что строка имеет длину 15 символов или меньше. Если это не так, тогда на консоль выводится сообщение об ошибке и происходит возврат без внесения изменений в поле empName.

На заметку! В случае класса производственного уровня проверку длины строки с именем сотрудника следовало бы предусмотреть также и внутри логики конструктора. Мы пока проигнорируем указанную деталь, но улучшим код позже, во время исследования синтаксиса свойств.

class Employee

{

  // Поля данных.

  private string _empName;

  ...

  // Метод доступа (метод get).

  public string GetName() => _empName;

  // Метод изменения (метод set).

  public void SetName(string name)

  {

    // Перед присваиванием проверить входное значение.

    if (name.Length > 15)

    {

      Console.WriteLine("Error! Name length exceeds 15 characters!");

                      // Ошибка! Длина имени превышает 15 символов!

    }

    else

    {

      _empName = name;

    }

  }

}

Такой подход требует наличия двух уникально именованных методов для управления единственным элементом данных. Чтобы протестировать новые методы, модифицируйте свой код следующим образом:

Console.WriteLine("***** Fun with Encapsulation *****\n");

Employee emp = new Employee("Marvin", 456, 30_000);

emp.GiveBonus(1000);

emp.DisplayStats();

// Использовать методы get/set для взаимодействия

// с именем сотрудника, представленного объектом.

emp.SetName("Marv");

Console.WriteLine("Employee is named: {0}", emp.GetName());

Console.ReadLine();

Благодаря коду в методе SetName() попытка указать для имени строку, содержащую более 15 символов (как показано ниже), приводит к выводу на консоль жестко закодированного сообщения об ошибке:

Console.WriteLine("***** Fun with Encapsulation *****\n");

...

// Длиннее 15 символов! На консоль выводится сообщение об ошибке.

Employee emp2 = new Employee();

emp2.SetName("Xena the warrior princess");

Console.ReadLine();

Пока все идет хорошо. Мы инкапсулировали закрытое поле empName с использованием двух открытых методов с именами GetName() и SetName(). Для дальнейшей инкапсуляции данных в классе Employee понадобится добавить разнообразные дополнительные методы (такие как GetID(), SetID(), GetCurrentPay(), SetCurrentPay()). В каждом методе, изменяющем данные, может содержаться несколько строк кода, в которых реализована проверка дополнительных бизнес-правил. Несмотря на то что это определенно достижимо, для инкапсуляции данных класса в языке C# имеется удобная альтернативная система записи.

<p id="AutBody_Root233">Инкапсуляция с использованием свойств</p>

Хотя инкапсулировать поля данных можно с применением традиционной пары методов get и set, в языках .NET Core предпочтение отдается обеспечению инкапсуляции данных с использованием свойств. Прежде всего, имейте в виду, что свойства — всего лишь контейнер для "настоящих" методов доступа и изменения, именуемых get и set соответственно. Следовательно, проектировщик класса по-прежнему может выполнить любую внутреннюю логику перед присваиванием значения (например, преобразовать в верхний регистр, избавиться от недопустимых символов, проверить вхождение внутрь границ и т.д.).

Ниже приведен измененный код класса Employee, который теперь обеспечивает инкапсуляцию каждого поля с использованием синтаксиса свойств вместо традиционных методов get и set.

class Employee

{

  // Поля данных.

  private string _empName;

  private int _empId;

  private float _currPay;

  // Свойства!

  public string Name

  {

    get { return _empName; }

    set

    {

      if (value.Length > 15)

      {

        Console.WriteLine("Error! Name length exceeds 15 characters!");

Перейти на страницу:

Похожие книги