- •Глава 13. Семантическое моделирование
- •Часть III Проектирование базы данных
- •Часть IV
- •14.1. Введение
- •14.2. Транзакции
- •14.3. Восстановление транзакции
- •14.4. Восстановление системы
- •14.5. Восстановление носителей
- •14.6. Двухфазная фиксация
- •14.7. Поддержка языка sql
- •14.8. Резюме
- •15.1. Введение
- •15.2. Три проблемы параллельности
- •15.3. Блокировка
- •15.4. Устранение трех проблем параллельности
- •15.5. Взаимная блокировка
- •15.6. Упорядочиваемость
- •15.7. Уровни изоляции
- •15.8. Блокировка намерения
- •15.9. Средства языка sql
- •15.10. Резюме
- •Часть V
- •16.1. Введение
- •16.2. Избирательная схема управления доступом
- •16.3. Мандатная схема управления доступом
- •16.4. Статистические базы данных
- •16.5. Шифрование данных
- •16.6. Средства языка sql
- •16.7. Резюме
- •17.1. Введение
- •17.2. Пример выполнения оптимизации
- •17.3. Оптимизация запросов
- •17.4. Преобразование выражений
- •17.5. Статистические показатели базы данных
- •17.6. Стратегия по принципу "разделяй и властвуй"
- •17.7. Реализация реляционных операторов
- •17.8. Резюме
- •18.1. Введение
- •18.2. Обзор концепции трехзначной логики
- •18.3. Некоторые следствия изложенной схемы
- •18.4. Отсутствующие значения и ключи
- •18.5. Внешнее соединение
- •18.6. Специальные значения
- •18.7. Поддержка неопределенных значений в языке sql
- •18.8. Резюме
- •Глава 19
- •19.1. Введение
- •19.2. Иерархия типов
- •19.3. Полиморфизм и заменимость
- •19.4. Переменные и операция присвоения
- •19.5. Специализация по ограничениям
- •19.6. Операции сравнения
- •19.7. Операторы, версии и сигнатуры
- •19.8. Является ли окружность эллипсом
- •19.9. Пересмотр специализации ограничением
- •19.10. Резюме
- •20.1. Введение
- •20.2. Предварительные сведения
- •20.3. Двенадцать основных целей
- •1. Локальная независимость
- •2. Отсутствие опоры на центральный узел
- •3. Непрерывное функционирование
- •4. Независимость от расположения
- •5. Независимость от фрагментации
- •6. Независимость от репликации
- •7. Обработка распределенных запросов
- •8. Управление распределенными транзакциями
- •9. Аппаратная независимость
- •10. Независимость от операционной системы
- •11. Независимость от сети
- •12. Независимость от типа субд
- •20.4. Проблемы распределенных систем
- •Транзакция т1х
- •20.5. Системы "клиент/сервер"
- •20.6. Независимость от субд
Глава 19
Наследование типов
19.1. Введение
В главе 13 уже рассматривались понятия подтипов и супертипов, а точнее— подти- пов и супертипов сущностей. Там же отмечалось, что если, например, некоторые слу- жащие являются программистами и все программисты являются служащими, то тип сущности PROGRAMMER можно рассматривать как подтип сущности EMPLOYEE, а тип сущ- ности EMPLOYEE — как супертип сущности PROGRAMMER. Но при этом подчеркивалось, что "тип сущности" не является типом в каком-либо формальном смысле, в частности по- скольку само понятие "сущность" определено довольно нестрого. В этой главе мы по- знакомимся с понятиями подтипов и супертипов поближе, но термин "тип" будем упот- реблять в более формальном и точном смысле, как в главе 5. Поэтому начнем с точного определения рассматриваемого термина.
■ Тип — это именованное множество значений (т.е. все возможные значения рас- сматриваемого типа) вместе со связанным множеством операторов, которые мо- гут применяться для значений и переменных данного типа.
Кроме того, добавим следующее.
Любой конкретный тип является либо системно определенным, либо пользова- тельским.
В определении любого конкретного типа указывается множество всех допустимых его значений (для этого, безусловно, используются ограничения типа, как указы- валось в главе 8).
Значения типа могут быть сколь угодно сложными.
Реальное или физическое представление каждого значения всегда скрыто от поль- зователя, т.е. типы отличаются от их реального представления. Однако каждый тип имеет хотя бы одно возможное представление, которое явно доступно поль- зователю через соответствующие операторы ТНЕ_ или их эквиваленты.
Значения и переменные каждого типа могут обрабатываться только с помощью операторов, определенных для этого типа.
К числу таких операторов, кроме упомянутых операторов ТНЕ_, относятся сле- дующие операторы.
а) По крайней мере один оператор выбора, точнее, один такой оператор для каж- дого предоставленного пользователю возможного представления. Он позволяет "выбрать" любое значение данного типа или указать его посредством соответ- ствующего вызова операции выбора.
б) Оператор равенства, который позволяет проверить, являются ли два произ- вольных значения данного типа на самом деле одним и тем же значением.
в) Оператор присвоения, позволяющий присвоить некоторое значение данного типа переменной, которая рассматривается как переменная данного типа.
г) Определенные операторы проверки типа, которые будут рассмотрены в раз- деле 19.6.
Замечание. Эти операторы могут оказаться ненужными, если отсутствует поддержка наследования.
Ко всему сказанному выше необходимо добавить следующее.
■ Одни типы могут являться подтипами других супертипов. Если В — это подтип типа А, то все операторы и ограничения типа, которые применимы к типу А, также применимы к типу В (наследование), но тип В в этом случае имеет еще и собст- венные операторы и ограничения типа, которые не применимы к типу А.
Например, предположим, что заданы два типа, ELLIPSE (Эллипс) и CIRCLE (Окружность), понимаемые в их обычном толковании. Тогда можно сказать, что тип CIRCLE — это подтип типа ELLIPSE (а тип ELLIPSE — это супертип типа CIRCLE). При этом подразумевается следующее.
Каждая окружность является эллипсом (т.е. множество всех окружностей является подмножеством всех эллипсов), однако обратное утверждение неверно.
Следовательно, каждый оператор, который применим к эллипсам вообще, безус- ловно, применим и к окружностям (поскольку окружности являются эллипсами), однако обратное утверждение неверно. Например, оператор THE_CTR (Определить центр) можно применять ко всем эллипсам, а значит, и к окружностям, но опера- тор THE_R (Определить радиус) можно применять только к окружностям.
Кроме того, любое ограничение, которое применимо к эллипсам вообще, приме- нимо и к окружностям в частности (опять же, поскольку окружности являются эллипсами), однако обратное утверждение неверно. Например, если эллипсы под- чиняются ограничению а > b (где а и b — его большая и малая полуоси соответ- ственно), то же самое ограничение должно выполняться и для окружностей. Из- вестно, что для окружностей полуоси а и b совпадают с радиусом г, а значит, ука- занное ограничение удовлетворяется тривиально, т.е. для окружностей на самом деле применимо более строгое ограничение а = Ь. Однако это ограничение не удовлетворяется для всех эллипсов в общем случае.
Замечание. Везде в этой главе не уточненный дополнительно термин "ограничение" будет использоваться для обозначения именно ограничения типа. Кроме того, тер- мины "радиус" и "полуось" здесь означают то, что точнее было бы назвать длиной радиуса или полуоси.
Таким образом, говоря нестрого, тип CIRCLE наследует операторы и ограничения от ти- па ELLIPSE, а также имеет собственные операторы и ограничения, которые не применимы к типу ELLIPSE. Обратите внимание, что подтип имеет подмножество значений, но в то же время — и супермножество свойств (этот аспект иногда служит источником путаницы!).
Замечание. Здесь и далее в этой главе под термином "свойства" мы будем подразуме- вать удобное сокращение для "совокупности операторов и ограничений".
Почему используется наследование типов
Почему тема наследования типов заслуживает отдельного рассмотрения? Имеется по меньшей мере два ответа на этот вопрос.
Во-первых, идеи выделения подтипов и наследования весьма широко распростра- нены в реальном мире, т.е. нет ничего необычного в такой ситуации, когда все значения типа имеют определенные свойства вообще и в то же время некоторое подмножество этих значений имеет собственные дополнительные специфические свойства. Поэтому выделение подтипов и использование механизма наследования представляются вполне полезными инструментами "моделирования реальности" (или семантического моделирования, как мы называли его в главе 13).
Во-вторых, если имеется возможность распознавать такие шаблоны, т.е. шаблоны выделения подтипов и наследования, то, включив информацию о них в программ- ное обеспечение приложений и систем, можно будет получить определенную практическую выгоду. Например, программу, которая применима для эллипсов, можно будет использовать и для окружностей даже в том случае, если первона- чально она создавалась без учета существования понятия окружностей (например, тип CIRCLE еще не был определен во время написания программы). Это так назы- ваемое преимущество повторного использования кода.
К сожалению, эти потенциальные возможности, как мы сейчас убедимся, не находят единодушной поддержки, поскольку нет единого мнения относительно формальной, строгой и абстрактной модели наследования типов, подтверждением чему может слу- жить следующее высказывание из [19.10].
"Основная идея наследования довольно проста... [тем не менее, несмотря на] ее ве- дущую роль в современных... системах, наследование— еще довольно спорный меха- низм... [Какого-либо] исчерпывающего представления о наследовании пока нет. "
Обсуждение в этой главе основывается на модели, разработанной автором вместе с Хью Дарвеном и подробно описанной в [3.3]. Поэтому предупредим читателя о том, что другие авторы в других текстах иногда вкладывают в такие термины, как "подтип" и "наследование", смысл, который несколько отличается от трактовки, принятой в настоя- щей книге.
Предварительные замечания
Существует ряд вопросов, в которых нужно разобраться, прежде чем переходить к обсуждению аспектов, непосредственно связанных с самим наследованием. В данном подразделе этим мы и займемся.
■ Значения имеют тип
Воспользуемся рассуждениями из главы 5. Если v — некоторое значение, то его можно представить как помеченное неким флажком значение с надписью "Я — целое", "Я — номер поставщика", "Я — окружность" и т.д. Поэтому при отсутст- вии наследования каждое значение будет относиться строго к одному типу. При использовании наследования значение может относиться к нескольким типам од- новременно, т.е. иметь тип ELLIPSE и CIRCLE в одно и то же время.
■ Переменные имеют тип
Каждая переменная имеет ровно один объявленный тип. Например, можно объя- вить переменную следующим образом.
VAR Е ELLIPSE ;
Здесь объявленный тип переменной Е — ELLIPSE. Если наследование не применя- ется, все возможные значения переменных имеют только один тип, а именно — соответствующий объявленный тип. Однако при использовании наследования данная переменная будет иметь значение, которое может относиться к нескольким типам одновременно, т.е. текущее значение переменной Е может быть эллипсом, который в действительности является окружностью, а потому относится и к типу ELLIPSE, и к типу CIRCLE в одно и то же время.
■ Одиночное и множественное наследования
Существует две разновидности наследования: одиночное и множественное. Вы- ражаясь неформально, одиночное наследование означает, что каждый подтип имеет ровно один супертип и наследует свойства лишь одного этого типа. В слу- чае множественного наследования каждый подтип может иметь любое количе- ство супертипов и наследовать свойства каждого из них. Очевидно, что первый вариант является частным случаем второго. Однако использование даже одиноч- ного наследования является достаточно сложной задачей (такое утверждение мо- жет показаться несколько неожиданным, но это действительно так). Поэтому в на- стоящей главе мы ограничимся обсуждением лишь одиночного наследования и под общим термином наследование (при отсутствии дополнительных пояснений) всегда будем подразумевать именно одиночное наследование. Заинтересованному читателю можно рекомендовать обратиться к [3.3], где подробно обсуждаются оба вида наследования, как множественное, так и одиночное.
■ Наследование скалярных значений, кортежей и отношений
Очевидно, что наследование возможно как для скалярных, так и для неска- лярных значений1, поскольку, в конце концов, эти нескалярные значения по- строены из скалярных значений. В частности, механизм наследования может применяться также к значениям кортежей и отношений. Однако даже насле- дование скалярных значений является весьма сложным механизмом (что, опять-таки, несколько неожиданно). Поэтому мы ограничимся рассмотрением лишь наследования скалярных значений и будем подразумевать, что не уточ- ненные дополнительно термины тип, значение и переменная означают тип, значение и переменную именно скалярного типа. В [3.3] можно найти сведе- ния обо всех видах наследования, а также о наследовании как скалярных зна- чений, так и кортежей и отношений.
Напомним, что скалярный тип — это такой тип, который не имеет компонентов, видимых пользователю. Пусть вас не вводит в заблуждение то, что скалярные типы имеют возможные представления, которые, в свою очередь, действительно имеют видимые пользователю компо- ненты, как указывалось в главе 5. Эти компоненты являются компонентами возможного пред- ставления, а не компонентами типа, несмотря на то что мы иногда для упрощения ссылаемся на них так, как будто они действительно являются компонентами типа.
■ Наследование структуры или поведения
Напомним, что скалярные значения могут иметь внутреннюю (физическую) структуру или представление произвольной сложности. Например, эллипсы и окружности, как нам уже известно, могут вполне законно считаться скалярными значениями, хотя их внутренняя структура может быть довольно сложной. Однако внутренняя структура всегда скрыта от пользователя. Значит, когда мы говорим о наследовании (по край- ней мере, в рамках нашей модели), мы не подразумеваем под этим наследование структуры, поскольку, с точки зрения пользователя, никакой структуры для наследова- ния просто нет! Другими словами, нас интересует так называемое наследование пове- дения, а не наследование структуры. (Здесь подразумевается "поведение" операто- ров, хотя, напомним, что в нашей модели наследуются и ограничения.)
Замечание. Безусловно, структурное наследование не исключается полностью. Однако, по нашему мнению, оно является вопросом, относящимся к реализации, а не к модели.
■ Подтаблицы и супертаблицы
К этому моменту читателю должно быть уже понятно, что обсуждаемая модель наследования связана с так называемым наследованием доменов (напомним, что домены и типы — это одно и то же). Однако, когда речь о возможностях наследо- вания идет в реляционном контексте, большинство чаще всего полагает, что име- ется в виду наследование таблиц. Например, в язык SQL3 включена поддержка концепции "подтаблиц и супертаблиц", в соответствии с которой определенная таблица В может наследовать все столбцы какой-то другой таблицы А и, кроме то- го, иметь собственные столбцы (см. приложение Б). Однако, на наш взгляд, идея "подтаблиц и супертаблиц" — это совершенно особый феномен, который, воз- можно, кому-то и интересен (хотя мы к этому относимся скептически [13.12]), но не имеет ничего общего с собственно наследованием типов.
И последнее замечание. В действительности тема наследования типа относится к дан- ным в целом, а не ограничивается лишь данными, хранимыми в базах данных. Поэтому из соображений простоты в большинстве примеров этой главы будут использоваться локаль- ные данные (обычные программные переменные и т.п.), а не данные базы данных.