Книга: ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание

Инкапсуляция на основе свойств класса

Инкапсуляция на основе свойств класса

В отличие от традиционных методов чтения и модификации, языки .NET тяготеют к реализации принципа инкапсуляции на основе использования свойств, которые представляют доступные для внешнего пользователя элементы данных. Вместо того, чтобы вызывать два разных метода (get и set) для чтения и установки данных состояния объекта, пользователь получает возможность вызвать нечто, похожее на общедоступное поле. Предположим, что мы имеем свойство с именем ID (код), представляющее внутренний член-переменную empID типа Employee. Синтаксис вызова в данном случае должен выглядеть примерно так.

// Синтаксис установки/чтения значения ID работника.
static void Main(string[] args) {
 Employee p = new Employee();
 // Установка значения.
 p.ID = 81;
 // Чтение значения.
 Console.WriteLine ("ID работника: {0} ", p.ID); Console.ReadLine();
}

Свойства типа "за кадром" всегда отображаются в "настоящие" методы чтения и модификации. Поэтому, как разработчик класса, вы имеете возможность реализовать любую внутреннюю логику, выполняемую перед присваиванием соответствующего значения (например, перевод символов в верхний регистр, очистку значения от недопустимых символов, проверку принадлежности числового значения диапазону допустимости и т.д.). Ниже демонстрируется синтаксис C#. использующий, кроме свойства ID, свойство Pay (оплата), которое инкапсулирует поле currPay, a также свойство Name (имя), которое инкапсулирует данные fullName.

// Инкапсуляция с помощью свойств.
public class Employee {
 ...
 private int empID;
 private float currPay;
 private string fullName;
 // Свойство для empID.
 public int ID {
  get {return empID;}
  set {
   // Вы можете проверить и, если требуется, модифицировать
   // поступившее значение перед присваиванием.
   empID = value;
  }
 }
 // Свойство для fullName.
 public string Name {
  get { return fullName; }
  set { fullName = value; }
 }
 // Свойство для currPay.
 public float Pay {
  get { return currPay; }
  set { currPay = value; }
 }
}

Свойство в C# компонуется из блока чтения и блока модификации (установки) значении. Ярлык value в C# представляет правую сторону оператора присваивания. Соответствующий ярлыку value тип данных зависит от того, какого сорта данные этот ярлык представляет. В данном примере свойство ID оперирует с типом данных int, который, как вы знаете, отображается в System.Int32.

// 81 принадлежит System.Int32,
// поэтому "значением" является System.Int32.
Employee e = new Employee();
e.ID = 81;

Чтобы это доказать, предположим, что вы добавили следующий программный код для установки свойства ID.

// Свойство для empID.
public int ID {
 get {return empID;}
 set {
  Console.WriteLine("value является экземпляром {0} ", value.GetType());
  Console.WriteLine("Значение value: {0} ", value); empID = value;
 }
}

Выполнив приложение, вы должны увидеть вариант вывода, показанный на рис. 4.5.


Рис. 4.5. Значение value после установки для ID значения 81

Замечание. Строго говоря, ярлык value в C# является не ключевым оловом, а, скорее, контекстным ключевым словом, представляющим неявный параметр, который используется в операторе присваивания в контексте метода, используемого для установки значения свойства. Поэтому вполне допустимо иметь члены-переменные и локальные элементы данных с именем value.

Следует понимать, что свойства (в отличие от традиционных методов чтения и модификации) еще и упрощают работу с типами, поскольку свойства способны "реагировать" на внутренние операции в C#. Например, предположим, что тип класса Employee имеет внутренний приватный член, представляющий значение возраста работника. Вот соответствующая модификация класса.

public class Employee {
 …
 // Текущий возраст работника.
 private int empAge;
 public Employee(string fullName, int age, int empID, float currPay) {
  …
  this.empAge = age;
 }
 public int Age {
  get { return empAge; }
  set { empAge = value; }
 }
 public void DisplayStats() {
  …
  Console.WriteLine("Возраст: {0} ", empAge);
 }
}

Теперь предположим, что вы создали объект Employee с именем joe. Вы хотите, чтобы в день рождения работника значение переменной возраста увеличивалось на единицу. Используя традиционные методы чтения и модификации, вы должны применить, например, следующий программный код.

Employee joe = new Employee();
joe.SetAge(joe.GetAge() + 1);

Но если инкапсулировать empAge, используя "правильный" синтаксис, вы сможете просто написать:

Employee joe = new Employee();
joe.Age++;

Оглавление книги


Генерация: 1.545. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз