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

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!");

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

      }

      else

      {

        _empName = value;

      }

    }

  }

  // Можно было бы добавить дополнительные бизнес-правила для установки

  // данных свойств, но в настоящем примере в этом нет необходимости.

  public int Id

  {

    get { return _empId; }

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

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