Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции - Часть 9.doc
Скачиваний:
35
Добавлен:
02.05.2014
Размер:
5.57 Mб
Скачать

9.12. Примеры наследования

Ниже мы приведем три примера наследования, иллюстрирующих применение суперклассов и подклассов, полиморфизма и динамического связывания, а также абстрактных классов.

9.12.1. Примеры суперклассов и подклассов. В банковской системе класс Счет имеет два атрибута: номерСчета и баланс. Поскольку счета нужно открывать и закрывать, дебетовать и кредитовать, а также считывать баланс, то определяются следующие операции:

§ открыть (номерСчета : Integer)

§ закрыть ()

§ читатьБаланс () : Real

§ кредитовать (сумма : Real)

§ дебетовать (сумма : Real)

Банк работает с двумя видами счетов: чековыми и сберегательными. Ситуа­ция выглядит вполне подходящей для применения наследования: нужно создать обобщенный суперкласс счета и его специализированные подклассы для чековых и сберегательных счетов. На данном этапе следует ответить на такие вопросы: ка­кие обобщенные атрибуты и операции должны быть в суперклассе и какие специ­ализированные атрибуты – у сберегательного и чекового счета? Должен ли су­перкласс быть абстрактным?

Но прежде чем отвечать, надо выявить сходство и различие между чековыми и сберегательными счетами. Сначала рассмотрим атрибуты. Ясно, что у любого счета есть номер и баланс, следовательно, эти атрибуты можно обобщить и по­местить в класс Счет. С другой стороны, в данном банке на сберегательные счета начисляются проценты, а на чековые - нет. Нужно знать сумму начисленных про­центов, поэтому в классе Сберегательный Счет объявляется атрибут накопительныйПроцент. Кроме того, со сберегательного счета разрешается безвозмезд­но снимать деньги не более трех раз в месяц, что приводит к объявлению атрибута счетчикДебетований. Еще объявляются два статических атрибута класса, их значение одинаково для всех объектов данного класса: максимальноеЧислоБесплатныхДебетований (сколько раз в месяц можно снимать деньги со счета, не оплачивая банковские услуги; начальное значение равно 3) и платаБанку (сум­ма, выделяемая банку за каждое снятие денег сверх лимита; равна 1,5 доллара). Кроме того, в случае чековых счетов желательно знать, какая сумма была положе­на в последний раз. Поэтому в классе Чековый Счет объявляется атрибут суммаПоследнегоВклада.

И для Чекового Счета, и для Сберегательного Счета нужны те же опера­ции, что и для обобщенного класса Счет: открыть, закрыть, читатьБаланс, кредитовать, дебетовать. Интерфейс этих операций определен в суперклассе Счет и наследуется обоими подклассами. Операции открыть, закрыть и кре­дитовать выполняются одинаково и для чековых, и для сберегательных счетов, поэтому их реализацию можно определить в классе Счет и унаследовать в под­классах. Что касается операции дебетовать, то Чековый Счет в состоянии уна­следовать ее реализацию от класса Счет. Но для Сберегательного Счета она осуществляется иначе: помимо уменьшения баланса необходимо еще увеличить счетчик Дебетований и вычесть из баланса платуБанку, если число дебетований превысило лимит. Нужна также дополнительная операция обнулитьСчетчикДебетований, которая сбрасывает значение счетчикаДебетований в начале каждого месяца.

Рис.9.10. Пример суперкласса и подклассов

На первый взгляд кажется, что операция читатьБаланс для обоих классов одинакова, но более внимательное рассмотрение показывает, что это не так. При обращении к чековому счету требуется получить баланс и сумму последнего вклада, а для сберегательного счета нужен баланс и накопительный процент. Следовательно, необходимо ввести разные операции чтения. В суперклассе опре­деляется обобщенная операция читатьБаланс, которая наследуется и чековым, и сберегательным счетом. Затем в класс Сберегательный Счет добавляется операция читать НакопительныйПроцент, а в класс Чековый Счет – операция читатьСуммуПоследнегоВклада.

Проект иерархии класса Счет показан на рис.9.10 и прокомментирован ниже.

Проект подкласса «Чековый Счет»

1. Атрибуты подкласса Чековый Счет:

– наследует атрибуты номерСчета и баланс. Оба атрибута объявлены за­щищенными в суперклассе Счет, поэтому они видимы в подклассах;

– добавляет атрибут суммаПоследнегоВклада.

2. Операции подкласса Чековый Счет:

– наследует операции открыть, закрыть, читатьБаланс, кредитовать и дебетовать;

– добавляет операцию читатьСуммуПоследнегоВклада () : Real

Проект подкласса «Сберегательный Счет»

1. Атрибуты подкласса Сберегательный Счет:

– наследует атрибуты номерСчета и баланс;

– добавляет атрибуты накопительныйПроцент и счетчик Дебетований;

– добавляет статические атрибуты класса максимальное ЧислоБесплатныхДебетований и платаБанку. Статические атрибуты в UML подчер­киваются (см. рис.9.10).

2. Операции подкласса Сберегательный Счет:

– наследует спецификацию и реализацию операций открыть, закрыть, читатьБаланс и кредитовать;

– наследует спецификацию операции дебетовать, но переопределяет ее реализацию: уменьшает баланс счета и взимает плату банку, если превы­шен месячный лимит бесплатных дебетований;

– добавляет операции:

– начислитьПроцент (процентнаяСтавка : Real). Ежедневное на­числение процентов;

– читатьНакопительныйПроцент () : Real;

– обнулитьСчетчикДебетований (). Сбрасывает счетчикДебетований в нуль в начале каждого месяца.

9.12.2. Пример полиморфизма и динамического связывания. Рассмотрим теперь создание объектов этих классов, а также пример полимор­физма и динамического связывания.

begin

private account : Счет;

Предложить клиенту ввести тип счета и снимаемую сумму

if клиент выбрал чековый счет

then -- Записать в переменную account чековый счет клиента.

. . .

account := customerCheckingAccount;

. . .

elseif клиент выбрал сберегательный счет

then -- Записать в переменную account сберегательный счет клиента.

. . .

account := customerSavingsAccount;

endif;

. . .

-- Дебетовать счет account, который может быть чековым или сберегательным.

account.дебетовать (сумма);

. . .

end;

В этом примере, если выбран чековый счет, то в переменную account запи­сывается объект класса Чековый Счет. При выполнении оператора account. дебетовать вызывается операция Чекового Счета. Если же указан сберега­тельный счет, то оператор account.дебетовать приведет к вызову операции Сберегательного Счета. Для чековых и сберегательных счетов выполняются разные варианты операции дебетовать, в частности для сберегательного счета из баланса дополнительно вычитается плата банку, если превышен месячный ли­мит дебетований.

Следует отметить, что объекту типа Счет можно присвоить объект типа Чековый Счет или Сберегательный Счет, но обратное неверно. Дело в том, что каждый Чековый Счет является Счетом, равно как и каждый Сберегательный Счет является Счетом, однако нельзя сказать, будто каждый Счет является Сберегательным, он может быть и Чековым.

9.12.3. Пример наследования абстрактному классу. Рассмотрим класс Техническое Обслуживание из системы круиз-контроля и мониторинга. Классы Замена Масла, Замена Воздушного Фильтра и Стан­ционное ТО можно проектировать отдельно, но, если сделать их подклассами класса Техническое Обслуживание, кода придется писать гораздо меньше. Иерархия обобщения/специализации для класса Техническое Обслуживание показана на рис.9.11.

Рис.9.11. Пример абстрактного суперкласса и подклассов

Суперкласс Техническое Обслуживание является абстрактным, в нем есть две операции: сбросить и проверить. Обе операции используют инкапсулиро­ванный тип данных начальныйПробег, который равен общему пути, пройденно­му к моменту предыдущего технического обслуживания. Операция сбросить вызывает операцию читать объекта Путь, которая возвращает значение полно­го Пробега, а затем присваивает это значение атрибуту начальный Пробег. Операция проверить абстрактная, она специфицирована в классе Техническое Обслуживание, но реализована только в его подклассах.

Любой подкласс, допустим Замена Масла, наследует структуру класса Тех­ническое Обслуживание, в том числе определение атрибута начальныйПробег и полное определение (спецификацию и реализацию) операции сбросить, а также спецификацию абстрактной операции проверить. Но реализацию последней опе­рации подкласс Замена Масла должен предоставить сам. Для нее требуется ука­зать расстояние, после которого масло надо менять (скажем, каждые 5 000км), и сообщение, выводимое, когда пробег с момента последней замены превысил за­данный порог. Нужно также задать операцию вывестиСообщениеО ЗаменеМасла, которая вызывается для объекта Интерфейс Индикатора ТО. Помимо этого, операция проверить вызывает операцию читать объекта Путь для получения текущего полного Пробега. Она вычитает из него значение начального Про­бега, чтобы выяснить, не прошла ли машина 5 000 км и не пора ли, следова­тельно, менять масло.

Соседние файлы в предмете Системы реального времени