
- •Лекция 2. С# и объектно-ориентированное программирование Формальное определение класса в с#
- •Ссылки на самого себя
- •Определение открытого интерфейса по умолчанию
- •Указание области видимости на уровне типа: открытые и внутренние типы
- •Столпы объектно-ориентированного программирования
- •Инкапсуляция
- •Наследование: отношения «быть» и «иметь»
- •Полиморфизм: классический и для конкретного случая
- •Средства инкапсуляции в с#
- •Реализация инкапсуляции при помощи традиционных методов доступа и изменения
- •Второй способ инкапсуляции: применение свойств класса
- •Поддержка наследования в с#
- •Применение модели включения-делегирования
- •Поддержка полиморфизма в с#
- •Абстрактные классы
- •Принудительный полиморфизм: абстрактные методы
- •Приведение типов в с#
- •Приведение числовых типов
- •Обработка исключений
- •Жизненный цикл объектов
- •Завершение ссылки на объект
- •Интерфейс iDisposable
- •Взаимодействие со сборщиком мусора
Поддержка наследования в с#
Теперь, когда вы уже умеете создавать хорошо инкапсулированные классы, обратимся к созданию в С# наборов взаимосвязанных классов при помощи наследования. Как уже говорилось, наследование — это один из трех основных принципов объектно-ориентированного программирования. Главная задача наследования — обеспечить повторное использование кода. Существует два основных вида наследования: классическое наследование (отношение «быть» — is-a) и включение-делегирование (отношение «иметь» — has-a). Мы начнем с рассмотрения средств СП для реализации классического наследования.
При установлении между классами отношений классического наследования вы тем самым устанавливаете между ними зависимость. Основная идея классического наследования заключается в том, что производные классы должны получать функциональность от базового класса-предка и дополнять ее новыми возможностями. Рассмотрим это на примере. Предположим, что в дополнение к нашему классу Employee мы определили еще два производных класса: класс Salesperson (продавец) и класс Manager (администратор). В результате получится иерархия классов, которая представлена на рис. 3.9.
Рис. 3.9. Иерархия классов сотрудников
Как видно из рисунка, сотрудниками являются и продавец, и менеджер. В модели классического наследования базовые классы (в нашем случае Employee) используются для того, чтобы определить характеристики, которые будут общими для всех производных классов. Производные классы (такие как Salesperson и Manager) расширяют унаследованную функциональность за счет своих собственных, специфических членов.
В С# указатель на базовый класс выглядит как двоеточие ( ). Если переводить наши отношения наследования между категориями сотрудников на язык синтаксиса СП, то соответствующий код может выглядеть следующим образом:
// Добавляем в пространство имен Employees два новых производных класса
namespace Employees
{
public class Manager: Employee
{
// Менеджерам необходимо знать количество имеющихся у них опционов на акции
private ulong numberOfOptions;
public ulong NumbOpts
{
get { return numberOfptions; }
set { numberOfOptions = value; }
}
}
public class Salesperson: Employee
{
// Продавцам нужно знать объем своих продаж
private int numberOfSales;
public int NumbSales
{
get { return numberOfSales; }
set { numberOfSales = value; }
}
}
В нашей ситуации оба производных класса расширяют функциональность базового класса за счет добавления свойств, уникальных для каждого класса. Поскольку мы использовали отношение «быть», то классы Salesperson и Manager автоматически наследовали от класса Employee все открытые члены. Это несложно проверить:
// Создаем объект производного класса и проверяем его возможности
public static int Main(string[ ] args)
{
// Создаем объект «продавец»
SalesPerson stan = new SalesPerson();
// Эти члены унаследованы от базового класса Employee
stan.EmpID = 100;
stan.SetFullName("Stan the Man");
// А это - уникальный член, определенный только в классе Salesperson
stan.NumbSales = 42;
return 0;
}
Конечно же, через объект производного класса нельзя напрямую обратиться • закрытым членам, определенным в базовом классе:
// Ошибка! Через объект производного класса нельзя обращаться к закрытым членам,
// определенным в базовом классе
Salesperson stan = newSalesPersonn();
stan.currPay;