Книга: C# для профессионалов. Том II

Наследование

Наследование

Теперь мы собираемся с помощью примера рассмотреть, как работает реализация наследования. Давайте предположим, что около года назад был поставлен пакет программного обеспечения и пришло время для следующей версии. Заказчики сделали замечание, что некоторые из их сотрудников являются на самом деле менеджерами, а менеджеры обычно получают бонусы в зависимости от прибыли, а также обычною зарплату. Это означает что метод GetMonthlyPayment() не дает полной информации для менеджеров. Вывод: необходимо добавить некоторый способ учета менеджеров.

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

Как можно при создании кода в VB обновить наше приложение? Существуют два возможных подхода, но оба они имеют серьезные недостатки. Можно:

? Написать новый класс Manager

? Изменить класс Employee

Создание нового класса является, вероятно, тем подходом, который потребует меньше всего работы так как можно начать с простого копирования кода модуля класса Employee и затем изменить эту копию кода. Проблема состоит в том, что Employee и Manager имеют такой большой объем общего кода, как весь код, связанный со свойствами Name, CompanyName и Salary. Дублирование одного и того же кода является опасным. Что произойдет, если в некоторый момент какая-то причина заставит изменить код? Плохой разработчик надеется не забыть внести одинаковые изменения в оба класса. Это самый простой способ создания ошибок. Другая проблема состоит в том, что теперь существуют два несвязанных класса Employee и Manager, с которыми должен иметь дело код клиента, что скорее всего сделает его написание затруднительным. (Хотя можно обойти эту проблему, помещая общие свойства в интерфейс и реализуя этот интерфейс в обоих классах Employee и Manager.)

Альтернативным способом является написание класса Manager и размещение объекта Employee внутри него как переменной с областью действия класса. Это решает проблему дублирования кода, но по-прежнему оставляет нас с двумя различными объектами, а также с неудобным, непрямым синтаксисом для вызова методов и свойств сотрудника (objManager.objEmployее.Name и т.д.).

Если выбрать модификацию модуля класса сотрудника, то по-видимому надо добавить дополнительное поле типа Boolean, которое указывает, является ли Employee менеджером или нет. Затем в соответствующих частях кода это Boolean будет проверяться в инструкции if, чтобы знать, что делать. Это решает проблему двух несвязанных классов — снова имеется только один класс. Однако это вносит новую трудность: как было специально сказано ранее, поддержку для менеджеров решено было добавить примерно год спустя. Это означает, что модуль класса Employee был по-видимому поставлен, протестирован, полностью отлажен и известно, что он работал правильно. В этой ситуации вряд ли возникнет желание обращаться к работающему коду, чтобы изменить его, учитывая связанный с этим риск внесения новых ошибок.

Другими словами, мы достигли точки, где VB не может предложить никакого удовлетворительного решения. Из заголовка этого раздела нетрудно сделать заключение, что C# предлагает способ решения этой проблемы с помощью использования наследования.

Мы уже видели, что наследование включает добавление или замену свойств классов. В предыдущем примере класс SquareRootForm добавил код к классу .NET System.Windows.Forms.Form. Он определил элементы управления для размещения в SquareRootForm как поля-члены, а также добавил обработчик событий. В примере Employee будут продемонстрированы как добавление, так и замена свойств базового класса, а также определен класс Manager, который является производным из класса Employee. Мы добавим поле и свойство, представляющие бонус, и заменен метод GetMonthlyPayment() (для полноты также будет заменен метод ToString(), чтобы он выводил бонус вместе с именем и зарплатой). Все это означает, что будет получен отдельный класс. Но при этом не потребуется дублировать никакой код и вносить большие изменения в класс Employee. Может показаться, что по-прежнему существует проблема двух различных классов, что делает более трудным написание клиентского кода, но, как будет продемонстрировано позже, C# имеет ответ и на это.

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


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