в этой главе представляют концепции
ПРИМЕЧАНИЕ
Фрагменты кода в этой главе представляют концепции объектно-ориентированного программирования. Помните: хотя я привожу много примеров кода на С#, сами концепции универсальны для ООП и не присущи какому-либо языку программирования. В этой главе будут также представлены для сравнения примеры на С, не являющемся объектно-ориентированным языком.
Допустим, вы пишете приложение для расчета зарплаты служащей вашей фирмы по имени Эми (Amy). Код на С, представляющий данные о служащем, будет выглядеть примерно так:
Struct EMPLOYEE {
char szFirstName[25];
char szLastName[25];
int iAge; double dPayRate;
};
Вот код для расчета зарплаты Эми Андерсон, в котором используется структура
EMPLOYEE:
void main()
{
double dTotalPay;
struct EMPLOYEE* pEmp;
pEmp = (struct EMPLOYEE*)malloc(sizeof(struct EMPLOYEE));
if (pEmp) {
pEmp->dPayRate = 100;
strcpy(pEmp->szFirstName, "Эми"); strcpy(pEmp->szLastName, "Андерсон"); pEmp->iAge = 28;
dTotalPay = pEmp->dPayRate * 40; printf("Bce выплаты Xs Xs составляют X0.2f",
pEmp->szFirstName, pEmp->szLastName, dTotalPay); >
free(pEmp);
}
Код этого примера основан на данных, содержащихся в структуре, и на некотором внешнем (по отношению к структуре) коде, обрабатывающем эту структуру. И что же здесь не так? Основной недостаток — в отсутствии абстрагирования: при работе со структурой
EMPLOYEE
необходимо знать чересчур много о данных, описывающих служащего. Почему это плохо? Допустим, спустя какое-то время вам потребуется определить "чистую" зарплату Эми (после удержания всех налогов). Тогда пришлось бы не только изменить всю клиентскую часть кода, работающую со структурой
EMPLOYEE,
но и составить описание (для других программистов, которым может достаться этот код впоследствии) изменений в функционировании программы.
Теперь рассмотрим тот же пример на С#: using System;
class Employee {
public Employee(string firstName, string lastName, int age, double payRate)
{
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
this.payRate = payRate; }
protected string firstName; protected string lastName; protected int age; protected double payRate;
public double CalculatePay(int hoursWorked)
{
// Здесь вычисляется зарплата.
return (payRate * (double)hoursWorked);
}
}
class EmployeeApp {
public static void MainQ
{
Employee emp = new Employee ("Эми", "Андерсон", 28, 100); Console.WriteLine("\n3apnflaTa Эми составляет $" +
emp.CalculatePay(40)); }
}
В С#-версии примера пользователю объекта для вычисления зарплаты достаточно вызвать его метод
CalculatePay.
Преимущество этого подхода в том, что пользователю больше не нужно следить, как рассчитывается зарплата. Если когда-нибудь потребуется изменить способ ее вычисления, то эта модификация не скажется на существующем коде. Такой уровень абстрагирования — одно из основных преимуществ использования объектов.
Сделаю одно замечание. В клиентской части кода на языке С можно создать функцию доступа к структуре
EMPLOYEE.
Однако ее придется создавать отдельно от структуры, которую она обрабатывает, и мы окажемся перед той же проблемой. А вот в объектно-ориентированном языке вроде С# данные объекта и методы их обработки (интерфейс объекта) всегда будут вместе.
Помните: модифицировать переменные объекта следует только методами этого же объекта. Как видно из нашего примера, все переменные-члены в
Employee
объявлены с модификатором доступа
protected,
a метод
CalculatePay —
с модификатором
public.
Модификаторы доступа применяются для задания уровня доступа, который получают производные классы к членам исходного класса. Модификатор
protected
указывает, что производный класс получит доступ к члену, а клиентский код — нет. Модификатор
public
делает член доступным и для производных классов, и для клиентского кода. Подробнее на модификаторах доступа я остановлюсь в главе 5, пока же запомните, что модификаторы позволяют защитить ключевые члены класса от нежелательного использования.
Содержание раздела