Скачиваний:
82
Добавлен:
02.05.2014
Размер:
2.28 Mб
Скачать

Глава 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 издание]