Скачиваний:
112
Добавлен:
02.05.2014
Размер:
2 Мб
Скачать
☆

Глава 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]), но не имеет ничего общего с собственно наследованием типов.

И последнее замечание. В действительности тема наследования типа относится к дан- ным в целом, а не ограничивается лишь данными, хранимыми в базах данных. Поэтому из соображений простоты в большинстве примеров этой главы будут использоваться локаль- ные данные (обычные программные переменные и т.п.), а не данные базы данных.

Соседние файлы в папке Дейт К. Дж. Введение в системы баз данных [7 издание]