Бертран Мейер - Основы объектно-ориентированного программирования
- Название:Основы объектно-ориентированного программирования
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Бертран Мейер - Основы объектно-ориентированного программирования краткое содержание
Фундаментальный учебник по основам объектно-ориентированного программирования и инженерии программ. В книге подробно излагаются основные понятия объектной технологии – классы, объекты, управление памятью, типизация, наследование, универсализация. Большое внимание уделяется проектированию по контракту и обработке исключений, как механизмам, обеспечивающим корректность и устойчивость программных систем.
В книге Бертрана Мейера рассматриваются основы объектно-ориентированного программирования. Изложение начинается с рассмотрения критериев качества программных систем и обоснования того, как объектная технология разработки может обеспечить требуемое качество. Основные понятия объектной технологии и соответствующая нотация появляются как результат тщательного анализа и обсуждений. Подробно рассматривается понятие класса - центральное понятие объектной технологии. Рассматривается абстрактный тип данных, лежащий в основе класса, совмещение классом роли типа данных и модуля и другие аспекты построения класса. Столь же подробно рассматриваются объекты и проблемы управления памятью. Большая часть книги уделена отношениям между классами – наследованию, универсализации и их роли в построении программных систем. Важную часть книги составляет введение понятия контракта, описание технологии проектирования по контракту, как механизма, обеспечивающего корректность создаваемых программ. Не обойдены вниманием и другие важные темы объектного программирования – скрытие информации, статическая типизация, динамическое связывание и обработка исключений. Глубина охвата рассматриваемых тем делает книгу Бертрана Мейера незаменимой для понимания основ объектного программирования.
Основы объектно-ориентированного программирования - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
При получении коробки с надписью "Животное" вместо ожидаемой надписи "Собака", можно соблазниться и все же ее открыть, зная, что, если внутри будет не собака, то потеряется право на возврат посылки и, в зависимости от того, что из нее появится, можно лишиться даже возможности рассказать эту историю. |
В таких случаях требуется новый механизм - попытка присваивания, который позволит писать команду вида r ?= p (где ?= обозначает символ попытки присваивания, в отличие от := для обычного присваивания), означающую "выполнить присваивание, если тип объекта соответствует r , а иначе сделать r пустым". Но мы пока не готовы понять, как такая команда сочетается с ОО-методом, поэтому вернемся к этому вопросу в следующих лекциях. (А до того, считайте, что вы ничего об этом не читали).
Полиморфное создание
Введение наследования и полиморфизма приводит к небольшому расширению механизма создания объектов, который позволит непосредственно создавать объекты типов-потомков.
Напомним, что команды создания (процедуры-конструкторы) имеют один из следующих видов:
create x
create x.make (...)
где вторая форма подразумевает и требует, чтобы базовый класс для типа T , приписанного x , содержал предложение creation, в котором make указана как одна из процедур-конструкторов. (Разумеется, процедура создания может иметь любое имя, - make рекомендуется по умолчанию). Результатом выполнения первой команды является создание нового объекта типа T , его инициализация значениями, заданными по умолчанию, и его присоединение к x . А при выполнении второй инструкции для создания и инициализации объекта будет вызываться make с заданными аргументами.
Предположим, что у T имеется собственный потомок U . Мы можем захотеть использовать x полиморфно и присоединить сразу к прямому экземпляру U , а не к экземпляру T . Возможное решение использует локальную сущность типа U .
some_routine (...) is
local
u_temp: U
do
...; create u_temp.make (...); x := u_temp; ...
end
Это работает, но чересчур громоздко, особенно в контексте многозначного выбора, когда захочется присоединить x к экземпляру одного из нескольких возможных типов наследников. Локальные сущности ( u_temp в нашем примере) играют только временную роль, их объявления и присваивания загромождают текст программы. Поэтому нужны специальные варианты конструкторов:
create {U} x
create {U} x.make (...)
Результат должен быть тот же, что и у конструкторов create, приведенных выше, но создаваемый объект должен являться прямым экземпляром U , а не T . Этот вариант должен удовлетворять очевидному ограничению: тип U должен быть согласован с типом T , а во второй форме make должна быть определена как процедура создания в классе, базовом для U , и если этот класс имеет одну или несколько процедур создания, то применима лишь вторая форма. Заметим, что здесь не важно, имеет ли сам класс T процедуры создания, - все зависит только от U .
Типичное применение связано с созданием экземпляра одного из нескольких возможных типов:
f: FIGURE
...
"Вывести значки фигур"
if chosen_icon = rectangle_icon then
create {RECTANGLE} f
elseif chosen_icon = circle_icon then
create {CIRCLE} f
else
...
end
Этот новый вид конструкторов объектов приводит к введению понятия тип при создании, обозначающего тип создаваемого объекта в момент его создания конструктором:
Для формы с неявным типом create x ... тип при создании есть тип x .
Для формы с явным типом create {U} x ... тип при создании есть U .
Динамическое связывание
Динамическое связывание дополнит переопределение, полиморфизм и статическую типизацию, создавая базисную тетралогию наследования.
Использование правильного варианта
Операции, определенные для всех вариантов многоугольников, могут реализовываться по-разному. Например, perimeter ( периметр) имеет разные версии для общих многоугольников и для прямоугольников, назовем эти версии perimeterPOL и perimeterRECT . У класса SQUARE также будет свой вариант (умноженная на 4 длина стороны). При этом естественно возникает важный вопрос: что случится, если программа, имеющая разные версии, будет применена к полиморфной сущности?
Во фрагменте
create p.make (...); x := p.perimeter
ясно, что будет использована версия perimeterPOL . Точно так же во фрагменте
create r.make (...); x := r.perimeter
будет использована версия perimeterRECT . Но что, если полиморфная сущность p статически объявлена как многоугольник, а динамически ссылается на прямоугольник? Предположим, что нужно выполнить фрагмент:
create r.make (...)
p := r
x := p.perimeter
Правило динамического связыванияутверждает, что версию применяемой операции определяет динамическая форма объекта. В данном случае это будет perimeterRECT .
Конечно, более интересный случай возникает, когда из текста программы нельзя заключить, какой динамический тип будет иметь p во время выполнения. Например, что будет во фрагменте
-- Вычислить периметр фигуры выбранной пользователем
p: POLYGON
...
if chosen_icon = rectangle_icon then
create {RECTANGLE} p.make (...)
elseif chosen_icon = triangle_icon then
create {TRIANGLE} p.make (...)
elseif
...
end
...
x := p.perimeter
или после условного полиморфного присваивания if ... then p := r elseif ... then p := t ..., ; или если p является элементом полиморфного массива многоугольников, или если p является формальным аргументом с объявленным типом POLYGON некоторой процедуры, которой вызвавшая ее процедура передала фактический аргумент согласованного типа?
Тогда в зависимости от хода вычисления динамическим типом p будет RECTANGLE , или TRIANGLE , или т.п. У нас нет никакого способа узнать, какой из этих случаев будет иметь место. Но, благодаря динамическому связыванию, этого и не нужно знать: что бы ни случилось с p , при вызове будет выполнен правильный вариант компонента perimeter .
Читать дальшеИнтервал:
Закладка: