Logo Море(!) аналитической информации!
IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware
Скидка до 20% на услуги дата-центра. Аренда серверной стойки. Colocation от 1U!

Миграция в облако #SotelCloud. Виртуальный сервер в облаке. Выбрать конфигурацию на сайте!

Виртуальная АТС для вашего бизнеса. Приветственные бонусы для новых клиентов!

Виртуальные VPS серверы в РФ и ЕС

Dedicated серверы в РФ и ЕС

По промокоду CITFORUM скидка 30% на заказ VPS\VDS

VPS/VDS серверы. 30 локаций на выбор

Серверы VPS/VDS с большим диском

Хорошие условия для реселлеров

4VPS.SU - VPS в 17-ти странах

2Gbit/s безлимит

Современное железо!

[Назад] [Оглавление] [Вперед]

4.2 Основы будущих систем баз данных

В качестве названия этого раздела была выбрана часть названия второго издания книги Дейта и Дарвена “Основы будущих систем баз данных: третий манифест” [20]. Этот выбор названия раздела не случаен, потому что раздел базируется на этой книге – она для него означает примерно то же, что книги [5] и [13] для подразделов 2.2 и 3.2 соответственно.

Прежде, чем переходить к основному материалу раздела, кратко представим содержание книги [20]. Прежде всего, заметим, что это второе издание, вышедшее в свет в 2000 г. Первое издание было опубликовано в 1998 г. под названием “Основы объектно/реляционных баз данных” [19]. Вот что пишут Д&Д по поводу изменения названия в предисловии ко второму изданию [20]: “Название первой редакции характеризовало Манифест как “основание объектно/реляционных баз данных”. Хотя эта характеристика была точной, она не была достаточной. Теперь мы считаем Манифест (как, впрочем, было всегда) основанием будущих баз данных вообще – включая, например, базы данных, содержащие темпоральные данные, и базы данных, используемые в связи с World Wide Wed .”

Однако, как кажется,  более вероятными причинами для смены названия были следующие обстоятельства:

  • Название первого издания могло вводить в заблуждение читателей, не слишком хорошо знакомых с подходом Д&Д. Термин “объектно-реляционные системы баз данных” достаточно давно закрепился за технологией, следующей идеям Второго манифеста и реализованной в разных формах в продуктах Informix , Oracle и IBM . Видимо, при выборе названия для первого издания своей книги Д&Д стремились подчеркнуть, что идеи именно Третьего манифеста могут привести к достижению тех целей, которые ставили перед собой создатели Второго манифеста.
  • Но независимо от того, присутствие слова “объектно” в названии первого издания книги противоречило явственно высказываемому Д&Д отношению к объектной технологии в области баз данных. Д&Д постоянно подчеркивают путаницу и туманность, связанные с использованием термина “объект” в “объектно-ориентированном мире”. Сами они используют (или стремятся использовать) это слово только в неформальном смысле. Но в этом случае неясно, как следует трактовать названием первого издания. Основы чего предлагают авторы?

Конечно, второе издание [20] появилось так скоро после выхода в свет первого издания не только и не столько потому, что авторы решили изменить название. В первом издании была недостаточно доработана часть книги, посвященная наследованию типов. За два года после выхода в свет этого издания Д&Д сумели построить законченную модель наследования, и именно желание представить полный вариант своих предложений побудило авторов к быстрым подготовке и публикации второго издания книги.

Второе издание [20] имеет следующую структуру. Основной текст книги разделен на четыре части: вступление, формальные спецификации, неформальные обсуждения и объяснения, подтипизация и наследование.

Первая часть книги состоит из двух вводных глав, написанных без привлечения каких-либо формализмов.  В главе 1 содержится базовая информация, поясняющая некоторые основополагающие идеи, лежащие в основе книги. В частности, обсуждаются ключевые логические различия между понятиями м одели и реализации; значения и переменной; значения, вида и кодировки значения. Глава 2 состоит из неформального обсуждения двух возможных подходов к ключевому вопросу интеграции объектов и отношений (что соответствует понятию объектного класса в реляционной модели данных?). Демонстрируется, что один из этих подходов является правильным, а другой – ложным.

Вторая часть книги носит наиболее формальный характер. В главе 3 приводится сам Третий манифест в том виде, как мы изложили его в подразделе 4.1. В главе 3 содержится определение новой реляционной алгебры (“A ”). В главе 4 определяется язык Tutorial D . Этот язык основывается на принципах, заложенных в Манифесте, и на алгебре A . Tutorial D служит основой для примеров в следующих главах книги. Он также позволяет судить о том, что могла бы представлять собой на практике СУБД, поддерживающая идеи Манифеста.

Третья часть представляет собой реальную сердцевину книги. Она состоит из шести глав, по одной для каждого из шести разделов Манифеста, как он определяется в главе 3. Эта часть, по существу, является сильно расширенным вариантом неформальных комментариев к предписаниям, запретам и очень строгим суждениям Третьего манифеста

Четвертая часть книги играет для подтипизации и наследования ту же роль, что первые три части . Так, глава 12 соответствует первой части (она содержит общее введение в тему ); глава 13 соответствует второй части (она содержит формальные определения); а главы 14, 15 и 16 соответствуют третьей части (они содержат расширенные, но неформальные пояснения и обсуждения этих формальных определений). Точнее, в главе 14 рассматривается только одиночное наследование при наличии скалярных типов; в главе 15 идеи, обсуждаемые в главе 14,  расширяются для включения  поддержки множественного наследования; в главе 16 в расчет принимаются также типы кортежей и отношений.

В дополнение к перечисленным главам в книге содержится одиннадцать приложений.

  • В приложении A определяется альтернативный вариант Tutorial D , основанный на реляционном исчислении, а не на реляционной алгебре.
  • Приложение B посвящено обсуждению “двух больших заблуждений” (приравнивание отношений и объектных классови смешение указателей и отношений).
  • В приложении C обсуждается “дилемма проектирования” (как лучше проектировать базу данных – в терминах структуры отношений или в терминах определяемых пользователем типов данных?).
  • В приложении D рассматриваются вопросы единиц измерения в контексте определения типов данных.
  • Приложение E посвящается критике применяемого в объектно-реляционном подходе механизма “супертаблиц и подтаблиц”.
  • В приложении F продолжается начатое в четвертой части книги обсуждение проблем, связанных с изменением семантики операций при определении типов данных с использованием наследования.
  • В приложении G критикуются подходы к наследованию типов, не основанные на специализации путем ограничения.
  • В приложении H подход Третьего манифеста сравнивается с подходом стандарта SQL :1999.
  • Аналогичное сравнение с подходом ODMG содержится в приложении I .
  • В приложении J приводится текст интервью, данного Д&Д по поводу Третьего манифеста в 1994 г.
  • В заключительном приложении (Приложении K) приводится аннотированный и согласованный список публикаций, используемых во всей книге.

В этом подразделе мы остановимся на следующих темах, обсуждаемых в книге [20]:

  • общие принципы;
  • система типов;
  • модель наследования и подтипизации.

Общие принципы

Здесь мы опираемся на материал первых двух глав [20]. Назначение материала состоит в том, чтобы ввести некоторую концептуальную базу для дальнейшего изложения.

Логические различия и логические ошибки, концептуальная целостность

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

Принцип концептуальной целостности, который Д&Дтакже относят к числу основополагающих, трактуется в том смысле, что с целью поддержания интеграции концепций необходимо поставить некоторые концепции на первое место. Рассматриваемые концепции должны быть тщательно отобраны, их должно быть как можно меньше, они должны быть согласованы и приемлемы по своей природе.

Некоторые ключевые логические различия

Существуют некоторые логические различия, которые имеют отношение ко всему дальнейшему – это различия между (a) моделью и реализацией, (b) значением и переменной, и (c) значением, видом и кодировкой.

Различие между моделью и реализацией определяется следующим образом:

  • Модель – это абстрактное, замкнутое, логическое определение объектов, операций и т.д., совместно представляющих абстрактную машину, с которой взаимодействуют пользователи.
  • Реализация данной модели – это физическая реализация компонентов модели на реальной компьютерной системе.

Различие между моделью и реализацией в действительности является важным частным случаем различия между логическим и физическим аспектами системы. Во всем Манифесте и во всей книге Д&Д имеют дело с абстрактной моделью, а не с вопросами реализации. (Под “реализацией” понимается реализация СУБД, а не некоторого приложения, работающего под управлением этой системы.)

Второе логическое различие – это различие между значениями и переменными (под переменной мы понимаем переменную в обычном смысле языка программирования). Используются следующие определения:

  • Значение – это “индивидуальная константа” (например, индивидуальная константа “3”).113 У значения нет позиции во времени и пространстве. Однако значения могут быть представлены в памяти (посредством некоторой кодировки), и у таких представлений (видов) имеется позиция во времени и пространстве: любое число различных переменных может иметь одно и то же значение одновременно или в разное время. По определению значение невозможно модифицировать.
  • Переменная – это контейнер вида значения. Переменная имеет позицию во времени и пространстве. Переменные, в отличие от значений, можно модифицировать; т.е. текущее значение данной переменной можно заменить другим значением, возможно, отличным от исходного.

Значения могут быть произвольно сложными; например, значение может быть массивом,   стеком, списком, отношением, геометрической точкой и т.д. Аналогичное замечание относятся и к переменным.

Третье логическое различие – это различие между собственно значением и видом этого значения в определенном контексте (например, в качестве текущего значения некоторой переменной). Одно и то же значение может одновременно проявляться в нескольких разных видах. Каждый из этих видов внутренним образом состоит из некоторой кодировки, или физического представления значения, и эти кодировки не обязательно одинаковы. Например, во множестве целых чисел целое значение 3 встречается ровно один раз, но любое число переменных одновременно может содержать виды этого целого числа в качестве своего текущего значения. Некоторые из этих видов могли бы быть физически представлены посредством, например, десятичной системы кодирования, а другие – на основе двоичной системы. Поэтому существует логическое различие между видом значения и кодировкой, которая применяется для внутреннего представления.

Следует заметить, что “вид значения” является концепцией модели, а “кодировка вида” относится к концепциям реализации. Например, пользователям может понадобиться знать, содержат ли две различные переменные виды одного и того же значения, но им не должно требоваться знать, используется ли для этих двух видов одно и то же физическое кодирование.

Типы данных и объектные классы

Чтобы иметь возможность детально обсуждать соотношение между объектной и реляционной технологиями, необходимо разобраться в том, какая концепция в реляционном мире является двойником концепции объектного класса в объектном мире.114 

Этот вопрос исключительно важен, поскольку объектный класс является фундаментальной концепцией объектного мира, и все остальные объектные понятия в большей или меньшей степени зависят от этой концепции. В качестве ответа на поставленный выше вопрос возможны два ответа: (a ) концепции объектного класса соответствует концепция домена; (b ) концепции объектного класса соответствует концепция отношения (вернее, переменной отношения, relvar ). Д&Д доказывают, что верен только первый ответ. При этом  в качестве аксиомы принимается то, что требуется оставаться в классической реляционной среде.

Для начала требуется навести должный порядок в реляционной терминологии. Как следует из классических определений реляционной модели данных, каждое отношение состоит из двух частей, заголовка и тела, где заголовок – это множество пар имя-столбца:имя-домена,

Предлагается следующий способ понимания природы отношений: Для заданного отношения R заголовок R обозначает некоторый предикат (истинностную функцию), а каждая строка тела R – это некоторое истинное высказывание, получаемое из предиката путем подстановки некоторых значений доменов вместо заменителей или параметров этого предиката (“инстанциация предиката”). Для примера рассмотрим отношение MMQ (“ведомость материалов”) (рис. 3.1).

MAJOR_P# : P#

MINOR_P# : P#

QTY : QTY

P1

P2

5

P1

P2

3

P2

P3

2

P2

P4

7

P3

P5

4

P 4

P 6

8

Рис. 3.1. Пример отношения ведомости материалов MMQ (в заголовке показаны имена атрибутов и доменов)

Заголовку отношения MMQ соответствует “деталь MAJOR _ P # содержит QTY деталей MINOR _ P # ”. Следующие высказывания являются истинными: “деталь P 1 содержит 5 деталей P 2 ” (получено подстановкой значений доменов P 1 , 5 и P 2 ); “деталь P 1 содержит 3 детали P 3” (получено подстановкой доменных значений P1 , 3 и P3 ) и т.д. Другими словами, домены состоят из вещей, о которых мы говорим; отношения состоят из истин, которые мы изрекаем по поводу этих вещей.

Из этого следует, что ( a ) необходимы и домены, и отношения (без доменов не о чем говорить, без отношений нельзя ничего сказать); ( b ) домены и отношения – это не одно и то же; домены и отношения достаточны, равно как и необходимы; с логической точки зрения больше ничего не требуется.

Когда люди говорят об отношениях, они очень часто имеют в виду переменные отношений, а не сами отношения. В действительности это частный случай логического различия между значениями и переменными. Например, значение данного отношения (множество строк) не меняется во времени, а значение переменной этого отношения меняется. Замечая, что подобно отношению и в отличие от переменной отношения значение данного домена (множество скаляров) также не меняется во времени, можно придти к ложному заключению, что домены и отношения являются вещами одного и того же вида. И наконец, смешение понятий собственно отношений и переменных отношений, приводит к тому (еще большему) заблуждению, что домены и переменные отношений – это одно и то же. Для достижения предельной ясности Д&Д вводят явный термин relvar как сокращенную форму от relation variable (переменная отношения) и высказываются в терминах relvars, а не отношений, когда имеются в виду действительно переменные отношения.

Теперь можно обсудить то соотношение понятий, которое Д&Д считают правильным – концепция домена соответствует концепции объектного класса. Обычно считается, что домен – это всего лишь концептуальный пул значений, из которого берутся реальные значения столбцов отношений. Такое понимание является удовлетворительным только до поры до времени. В действительности, домен – это то же самое, что тип данных – определенный в системе или  определенный пользователем тип. Поэтому эти термины  являются взаимозаменяемыми. С понятием типа данных ассоциируется понятие операций, которые допускается применять к значениям этого типа (со значениями типа можно работать только посредством применения операций, определенных для этого типа).

Различаются собственно тип (или домен) и внутреннее представление,или физическая кодировка значений этого типа внутри системы. Например, номера деталей могли бы быть представлены внутренним образом как строки символов, но отсюда не следует, что можно производить операции с номерами деталей как со строками символов. Операции, определяемые для данного типа, зависят от предполагаемого смысла или семантики этого типа, а не от способа представления значений типа в системе. Внутренние представления значений типа должны быть скрыты от пользователя. Подобная строгая типизация в понимании Д&Д означает, что (a) у каждого значения имеется тип и (b) при попытке выполнения любой операции система проверяет, что операнды имеют типы, допустимые для этой операции.

В реляционной модели нет ничего, для чего требовалось бы ограничить типы данных  только простыми формами. Единственным требованием является то, что значениями домена можно манипулировать только посредством определенных для него операций; внутреннее представление должно быть скрыто. Другими словами, вопрос о том, какие поддерживаются типы данных, ортогонален вопросу поддержки реляционной модели.

Итак, в реляционном мире домен – это тип данных, определяемый системой или пользователем, значениями которого можно манипулировать только с помощью определенных для него операций (и внутреннее представление которого может быть произвольно сложным, но скрытым от пользователя). Если обратиться к объектному миру, выясняется, что самое фундаментальное среди всех понятий, объектный класс, это тип данных, определенный системой или пользователем, значениями которого можно манипулировать исключительно посредством операторов, определенных для этого типа (и внутреннее представление которого может быть сколь угодно сложным, но скрытым от пользователя).  Другими словами, домены и объектные классы – это одно и то же; это обеспечивает ключ к интеграции двух технологий, и именно эта позиция отстаивается в Третьем Манифесте.

Уравнивание объектного класса с relvar является серьезной логической ошибкой. По мнению Д&Д истоки этой ошибки кроятся в синтаксической близости определений класса и переменной отношения. Принципиальное различие понятий заключается в том, что relvar – это переменная, а класс – это тип. (Переменная отношения и домен - это не одно и то же.) Это уже показывает ошибочность уравнивания объектного класса с relvar . Более подробный анализ позволяет придти к выводу, что принятие второго вида уравнивания понятий подрывает концептуальную целостность реляционной модели.

Резюме

В объектной технологии имеется одна безусловно хорошая идея – определяемые пользователями типы (включая определяемые пользователями операции). Одна идея является вероятно хорошей – наследование типа (хотя не здесь судить, насколько именно хорошей ). Ключевой технической идеей Третьего Манифеста является то, что эти две идеи полностью ортогональны реляционной модели. Чтобы достичь желательной объектной функциональности,  не надо абсолютно ничего делать с реляционной моделью.

Пользователям требуются истинно реляционные СУБД (“истинно реляционные системы” не означают SQL-ориентированные системы), в которых содержится должная поддержка доменов, и тогда они получат “объектно/реляционные” СУБД, которых добивались. Привлекательность собственно объектных СУБД (в противоположность “объектно/реляционным” СУБД) можно целиком объяснить частичной неудачей существующих поставщиков SQL-ориентированных систем в части должной поддержки реляционной модели. Но это не является аргументом для отказа от реляционной модели.

Система типов

Здесь мы кратко обсудим основные положения [20], связанные с построением системы типов, собрав воедино развернутые комментарии Д&Д к разным предписаниям, запретам и очень строгие суждения Третьего манифеста.

Скалярные типы

Термин тип охватывает и скалярные и не скалярные типы. Между скалярными и не скалярными типами имеется принципиальное различие. Скалярные типы вне зависимости от уровня сложности их реальных представлений – не содержат компонентов, видимых для пользователя.115 Напротив, не скалярные типы  содержат видимые для пользователя компоненты; в частности, типы кортежей и отношений не являются скалярными и содержат наборы видимых для пользователя атрибутов.

 

Значения некоторого скалярного типа обобщенно называются скалярными значениями (для краткости, скалярами). Аналогично, переменные, значения которых ограничиваются скалярами, обобщенно называются скалярными переменными. Реальное представление  таких значений и переменных может быть сколь угодно сложным.

Скалярные типы могут определяться пользователями либо быть системно-определенными (“встроенными”). Требуется, чтобы поддерживался хотя бы один встроенный скалярный тип – тип истинностного значения. Для определенности предполагается, что для этого типа поддерживаются операции NOT , AND и OR и литералы TRUE и FALSE . Для удобства считается, что поддерживаются также встроенные скалярные типы INTEGER , RATIONAL (Д&Д предпочитают использовать этот термин вместо REAL ) и CHAR с соответствующими операциями и литералами.

Вот несколько примеров определений пользовательских скалярных типов (используется синтаксис Tutorial D , который в данном случае не требует пояснений).

TYPE S# POSSREP { CHAR } ;
TYPE QTY POSSREP { INTEGER CONSTRAINT QTY > 0 } ;

Здесь у типа S # имеется только одно объявленное возможное представление (“POSSREP ”), обладающее именем S # по умолчанию.116У этого возможного  представления имеется ровно один компонент, имя которого по умолчанию совпадает с именем возможного представления, т.е. опять S # . Поскольку этот компонент определяется как принадлежащий типу CHAR , и не указано какое-либо дополнительное ограничение для типа S # , множество допустимых значений этого типа является множеством всех значений, которые можно представить в виде символьных строк. Тип QTY определяется аналогичным образом, но для него указано дополнительное ограничение –  значения этого типа должны быть положительными.

Вот несколько более сложных примеров определения скалярных типов:

TYPE LENGHT POSSREP { L RATIONAL } ;

TYPE POINT
     POSSREP POINT { X LENGHT, Y LENGHT
                     CONSTRAINT … } ;
     POSSREP POLAR { R LENGHT, THETA ANGLE
                     CONSTRAINT … } ;

TYPE POLYGON
     POSSREP { VERTICES
               RELATION { V# INTEGER, VERTEX POINT
               CONSTRAINT … } ;

Определение типаLENGTH аналогично ранее приведенным определениям типов за исключением того, что единственному компоненту возможного представления этого типа задано явное имя L . ТипPOINT (“точка”) отличается от предыдущих примеров тем, что у него есть два различных объявленных возможных представления: первое –POINT (у этого возможного представления то же имя, что и у типа), с компонентами (Декартовыми координатами) X и Y , и второе – POLAR с компонентами (полярными координатами)R и THETA . Только в тех случаях, когда заданный тип имеет два или более объявленных возможных представлений, необходимо давать таким возможным представлениям явные имена. ТипELLIPSE (“эллипс”) отличается от предыдущих примеров тем, что его объявленное возможное представление основано не на встроенных, а на определенных пользователем типахLENGTH и POINT . Наконец, типPOLYGON (“многоугольник”) отличается от предыдущих примеров тем, что единственный компонент его объявленного возможного представления VERTICES принимает значения-отношения. То есть многоугольник представлялся бы отношением, содержащим по одному кортежу для каждой вершины этого многоугольника; этот кортеж содержал бы номер вершины (значение типаINTEGER ) вместе с самой соответствующей вершиной (значение типа POINT ).

Следует подчеркнуть, что операция определения типа реально не создает соответствующего множества значений. Концептуально, это множество значений уже существует и всегда будет существовать. Все, что делает операция “определения типа”, заключается в введении имени, посредством которого можно ссылаться на это множество значений. Из RM -предписания 2 следует, что любое значение всегда относится к одному и только одному типу (если не поддерживается наследование). Побочным (но важным) следствием является то, что пересечение множеств значений любых двух различных типов всегда пусто (опять же при отсутствии наследования).

Скалярная операция – это операция, возвращающая скалярное значение или обновляющая скалярную переменную. 117  Как и скалярные типы, скалярные операции могут определяться либо пользователями, либо системой (“встраиваться”). Встроенные операции определяются только в связи со встроенными типами. Предполагается, что для встроенных скалярных типов BOOLEAN , INTEGER , RATIONAL и CHAR поддерживается естественный для этих типов набор операций, причем имена некоторых операций перегружены. Определяемые пользователями операции можно определять как для встроенных типов, так и для определяемых пользователями.

Факт существования операции с заданным именем не препятствует возможности перегрузки – то есть определения другой операции с тем же именем, но с другими объявленными типами параметров и (возможно) результатов, и следовательно, по крайней мере, частично отличной семантикой. Можно было бы даже не только перегрузить, но и переопределить существующую операцию посредством определения другой операции с тем же именем и теми же объявленными типами параметров и результатов, но с другой семантикой. По очевидным соображениям, мы рекомендуем, чтобы это средство использовалось со всеми возможными предосторожностями.  

Вот пример определяемой пользователем скалярной операции, работающей со встроенным типом: 

OPERATOR ABS ( N RATIONAL ) RETURNS RATIONAL ;
   RETURN CASE
             WHEN N ³ 0.0 THEN +N
             WHEN N < 0.0 THEN –N
          END CASE ;
END OPERATOR ;

Операция ABS определяется с единственным параметром N объявленного типа RATIONAL и возвращает результат того же объявленного типа. Это операция только чтения, что означает, что ни при каком вызове функция не пытается обновлять свой собственный аргумент.

Вот другой пример определяемой пользователем скалярной операции только чтения, которая работает с некоторыми определяемыми пользователем типами:

OPERATOR DIST ( P1 POINT, P2 POINT ) RETURNS LENGTH ;
   RETURN WITH THE_X ( P1 ) AS X1 ,
            THE_X ( P2 ) AS X2 ,
            THE_Y ( P1 ) AS Y1 ,
            THE_Y ( P2 ) AS Y2 ,
            SORT ( ( X1 - X2 ) ** 2 + ( Y1 - Y2 ) ** 2 ) ) ;
END OPERATOR ;

Эта операция, DIST (“расстояние”) определяется с двумя параметров P 1 и P 2 объявленного типа POINT , и возвращает результат объявленного типа LENGTH . Операции THE _ X и THE _ Y используются для получения координат X и Y двух рассматриваемых точек, затем эти координаты используются для получения требуемого расстояния. WITH позволяет ввести сокращения для некоторых выражений.

Для определенности принимается, что аргументы вызовов операций задаются в  позиционной нотации, т.е. в данном вызове i -й аргумент в списке аргументов  соответствует i -му параметру в списке параметров определения операции.

Вот пример операции обновления:

OPERATOR REFLECT ( P POINT ) UPDATES P ;
   BEGIN ;
      THE_X ( P ) := THE_X ( P ) ;
      THE_Y ( P ) := THE_Y ( P ) ;
      RETURN ;
END OPERATOR ;

Операция REFLECT фактически перемещает точку с декартовыми координатами (x ,y ) в центрально-симметричную точку (- x ,- y ). Операция определяется с одним параметром P объявленного типа POINT и при вызове должным образом обновляет аргумент, соответствующий этому параметру. Как в предыдущем примере, операции THE _ X и THE _ Y используются для “чтения” координат X и Y заданной точки; псевдопеременныеTHE _ X и THE _ Y используются для обновления этих координат. Вызов REFLECT не возвращает результата; такой вызов не имеет значения и не является скалярным выражением. Поэтому вызов должен выполняться посредством явного оператора CALL (или некоторого его логического эквивалента).

По поводу приведенных примеров следует сделать несколько замечаний:

  • С уществует существенное логическое различие между (a ) формальными операндами, или параметрами, в терминах которых определяется данная операция и (b ) реальными операндами, или аргументами, которые передаются любому вызову этой операции. (Эта разница становится особенно значительной, если поддерживается наследование типов.)
  • Объявленный тип каждого аргумента должен быть в точности тем же, что и объявленный тип соответствующего параметра (исключения возможны, если поддерживается наследование типов).
  • Важное логическое различие имеется между операциями обновления и операциями только чтения. Операции обновления применяются к переменным, а не к значениям. Следовательно, операции только чтения применяются к значениям (в частности, они  применимы к значениям, которые являются текущими значениями переменных); операции обновления применяются именно к переменным.
  • Когда вызывается операция обновления, аргументы, соответствующие параметрам, которые являются предметом обновления (аргументы, соответствующие параметрам, указанным в спецификации UPDATES ), должны быть заданы как переменные, а не как произвольные выражения, и при вызове операции этим переменным потенциально присваиваются значения.  Другие аргументы таких вызовов (и все аргументы вызовов операций только чтения) могут быть специфицированы как произвольные выражения.
  • Аргументы, которые соответствуют параметрам, являющимся предметом обновления, всегда передаются по ссылке, из чего следует, что операции над этими параметрами являются в действительности операциями над соответствующими аргументами (в частности, присваивание значения такому параметру в действительности присваивает значение соответствующему аргументу). Все другие аргументы передаются по значению, и операции над соответствующими параметрами в действительности являются операциями над “фиктивными” (создаваемыми системой) аргументами, которым задаются те же значения, что и подлинным аргументам.
  • Поскольку вызов скалярной операции только чтения возвращает скалярный результат,  такой вызов представляет собой частный случай скалярного выражения. Он может появиться везде, где может появиться вызов скалярного селектора. Таким образом, посредством вложения вызовов скалярных операций только чтения может быть построено скалярное выражение любой сложности.
  • Поскольку системе известны объявленные типы всех параметров и всех результатов скалярных операций, система знает, какие скалярные выражения допустимы (т.е. не приводят к возникновению ошибок, связанных с типами). Система знает также тип результата каждого такого допустимого выражения. Такой тип называется объявленным типом скалярного выражения.
  • Поскольку вызов операции обновления не возвращает результата, такой вызов стоит рассматривать как оператор, а не как выражение. В частности, он не может выступать в качестве аргумента для других вызовов операций.

Как отмечалось ранее, в определении любого скалярного типа должно указываться по крайней мере одно объявленное возможное представление для значений этого скалярного типа (и при таком заданном скалярном типе T и таком возможном представлении PR каждое значение типа T должно быть представимо посредством PR ).118Объявление возможного представления автоматически приводит в действие поддержку соответствующего селектора (и нельзя обеспечить селекторы никаким другим способом). Следовательно, селекторы и возможные представления находятся во взаимно однозначном соответствии друг с другом (параметры селекторов и компоненты возможных представлений находятся также во взаимно однозначном соответствии). Поэтому можно принять соглашение о задании селектору и соответствующему возможному представлению одного и того же имени (хотя они являются логически различными понятиями).

Следует подчеркнуть различия между вызовами селекторов вообще и литералами в частности. Коротко говоря, все литералы являются вызовами селекторов, но не все вызовы селекторов являются литералами. Вызов селектора является литералом тогда и только тогда, когда его аргументы (если они есть) в свою очередь являются литералами. Таким образом, литерал является символом, который обозначает некоторое фиксированное значение, которое определяется на все времена конкретным рассматриваемым символом. Объявленный тип этого символа (который является, конечно, частным случаем выражения) также определяется самим.

Вернемся к примеру определяемого пользователем типа POINT , чтобы обсудить  вопросы определения и реализации типов. Повторим в упрощенном виде определение этого типа:

TYPE POINT
     POSSREP POINT  { X LENGTH, Y LENGTH }
     POSSREP POLAR { R LENGTH, THETA ANGLE } ;

В данном примере в определении типаспецифицированы два объявленных возможных представления –  POINT и POLAR . Следовательно, будут существовать две соответствующие операции выбора: POINT , которая позволяет пользователю задавать декартовы координаты X и Y как два значения типа LENGTH и возвращает соответствующее значение типа POINT , и POLAR , которая позволяет пользователю задавать полярные координаты R и THETA как значения типов LENGTH и ANGLE соответственно и возвращает соответствующее значение типа POINT .


Предположим, что представление с декартовыми координатами на самом деле является реальным. Тогда в системе будут поддерживаться высоко защищенные операции, не входящие в D ,  которые раскрывают это реальное представление, и реализатор типа будет использовать эти операции для реализации требуемых селекторов POINT и POLAR . Вот, например, возможная реализация (псевдокод) для селектора POINT :

OPERATOR POINT ( X LENGTH, Y LENGTH ) RETURNS POINT ;
   BEGIN ;
      VAR P POINT ;
      P.X   :=  X ;          /* assign to actual representation */
      P.Y   :=  Y ;          /* assign to actual representation */
      RETURN P ;
   END ;
END OPERATOR ;

“Высоко защищенные операции, не входящие в D ” представлены в приведенном коде посредством точечной нотации. Селектор POLAR также мог бы быть реализован “вне среды D ” (снова псевдокод): 

OPERATOR POLAR ( R LENGTH, THETA ANGLE ) RETURNS POINT ;
   BEGIN ;
      VAR P POINT ;
      P.X   :=  R * COS ( THETA ) ;           
      P.Y   :=  R * SIN ( THETA ) ;           
      RETURN P ;
   END ;
END OPERATOR ;

Но селектор POLAR , возможно, менее эффективно мог бы быть реализован в терминах селектора POINT :

OPERATOR POLAR ( R LENGTH, THETA ANGLE ) RETURNS POINT ;
   RETURN POINT ( R * COS ( THETA ), SIN ( THETA ) ) ;
END OPERATOR ;

Из всего этого следует, что реализаторы типа(но не определители типа и, конечно, не пользователи типа) должны на самом деле знать реальные представления.

Пусть PR - это возможное представление скалярного типа T , и пусть у PR имеются компоненты C 1 , C 2 , …, Cn . Определим THE _ C 1 , THE _ C 2 , …, THE _ Cn как семейство операций, таких что для каждогоi (i = 1, 2, …, n ), операция THE _ Ci обладает следующими свойствами:

  • Ее единственный параметр имеет тип T .
  • Если ссылка на операцию, появляется в позиции “источника” (в частности, в левой части присвоения), то операция возвращает компонент Ci своего аргумента. (Точнее, она возвращает значение компонента Ci возможного представления PR ( v ) значения своего аргумента v .)
  • Если ссылка на операцию, появляется в позиции “цели” (в частности, слева от присвоения), то:
  • Аргумент должен быть явно указан как переменная, а не произвольное выражение.
  • Ссылка действует как ссылка на псевдопеременную, и это означает, что она реально обозначает компонент Ci этого аргумента, а не только возвращает значение его значение. (Точнее, она обозначает компонент Ci возможного представления PR ( V ) аргумента-переменной V .)

Несколько примеров :

TYPE TEMPERATURE POSSREP CELSIUS { C RATIONAL } ;

VAR TEMP TEMPERATURE ;
VAR CEL RATIONAL ;

CEL  :=  THE_C ( TEMP ) ;
THE_C ( TEMP )  :=  CEL ;

В первом присваивании температура, измеренная в градусах Цельсия, которая является текущим значением переменной TEMP типа TEMPERATURE , присваивается переменной CEL типа RATIONAL ; во втором – текущее значение переменной CEL типа RATIONAL , рассматриваемое как температура в градусах Цельсия, используется для обновления переменной TEMP типа TEMPERATURE . Операция THE _ C фактически раскрывает возможное представление температуры посредством “градусов Цельсия” как для целей обновления, так и для целей только чтения. Но это возможное представление не обязательно является реальным представлением; например, температуру можно было бы представлять в градусах Фаренгейта, а не в градусах Цельсия.

Вот немного более сложный пример:

TYPE POINT POSSREP POINT { X LENGTH, Y LENGTH } ;

VAR L LEHGTH ;
VAR P POINT ;

L  :=  THE_X ( P ) ;
THE_X ( P )  :=  L ;

В первом присваивании переменной L типа LEHGTH присваивается координата X точки, являющейся текущим значением переменной P типа POINT ; во втором – текущее значение переменной L типа LEHGTH используется для обновления координаты X переменной P типа POINT . Операции THE _ X и THE _ Y фактически раскрывают возможное представление точек посредством “Декартовых координат” как для целей обновления, так и для целей только чтения; и снова это возможное представление не обязательно совпадает с реальным представлением.

    

Заметим теперь, что псевдопеременные THE _ логически необязательны. Рассмотрим второе присваивание в первом примере. Это присваивание, в котором используется псевдопеременная, логически эквивалентно другому, в котором псевдопеременная не используется:

TEMP   :=  CELSIUS ( CEL ) ;    /* вызов селектора CELSIUS */

Вот логический эквивалент второго присваивания во втором примере без использования псевдопеременной:

P  :=  POINT ( L, THE_Y ( P ) ) ;    /* вызов селектора POINT */

Другими словами, псевдопеременные как таковые не являются строго необходимыми для поддержки обсуждаемой разновидности обновления на уровне компонентов. Однако подход с использованием псевдопеременных интуитивно выглядит более привлекательным, чем альтернативный (для которого первый подходможно рассматривать как сокращенную форму); более того, он также обеспечивает высокую степень устойчивости к изменениям синтаксиса соответствующего селектора. 

Заметим также, что по поводу реализации операций раскрытия возможного представления можно сделать замечания, аналогичные тем, которые приводились выше  в связи с операциями выбора значений скалярного типа.

Типы кортежей и отношений

Кортежные типы и типы отношений являются генерируемыми типами, получаемыми путем применения генераторов типа TUPLE и RELATION соответственно. Вот пример использования кортежного типа:

VAR ADDR TUPLE { STREET CHAR,
                CITY   CHAR,
                STATE  CHAR,
                ZIP    CHAR } ;

Здесь определяется кортежная переменная ADDR типа

TUPLE { STREET CHAR, CITY CHAR, STATE CHAR, ZIP CHAR }

Это пример генерируемого (кортежного) типа. Каждая из комбинаций “имя : тип” является атрибутом этого кортежного типа, и множество всех таких атрибутов является заголовком кортежного типа. Мощность этого множества называется степенью  кортежного типа. Кортежная переменная ADDR имеет те же самые атрибуты, заголовок и степень, и то же касается всех возможных значений этой переменной.

Умышленно не поддерживается отдельная операция “определения типа кортежа”. Одним из оснований для такого решения является то, что иначе потребовалось бы вводить имя кортежного типа (помимо уже существующего имени TUPLE {…}). Такие дополнительные имена усложнили бы другие аспекты предлагаемого Д&Д подхода, например, решения вопроса о том, когда два типа совпадают.119 По этим соображениям предписывается, чтобы кортежные типыиспользовались “в виде подстановки”, как часть операции, которая определяет кортежную переменную отдельно.

Для кортежных типов требуется поддержка “операций, аналогичных операциям RENAME , project , EXTEND и JOIN из реляционной алгебры”. Вот несколько примеров, не требующих специальных пояснений (в последнем примере присутствует вызов селектора кортежей – фактически, кортежный литерал):

ADDR RENAME ZIP AS POSTCODE   /* переименование атрибута кортежа */

ADDR RENAME PREFIX ' ST ' AS ' G ' /* то же самое, префиксный вариант */

ADDR   { STATE , ZIP }                        /* проекция кортежа */

EXTEND ADDR ADD NAME ('Clark Kent') AS NAME /* расширение кортежа */

ADDR JOIN                            /* соединение кортежей */
    TUPPLE { NAME NAME ('Clark Kent') ,  COUNTRY 'USA' }

Вот пример присваивания кортежей:

ADDR  :=  TUPLE {STREET 'One Jacob Way' ,
                 CITY   'Reading' ,
                 STATE  'Massachusetts' ,
                 ZIP    '01870' } ;

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

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

VAR STATE_VAR CHAR ;

STATE_VAR := STATE FROM ADDR ;

Явно допускается, чтобы кортежи (и отношения) включали атрибуты, значениями которых были бы кортежи. Операции, которые применяются к этим кортежным значениям, это в точности те же операции языка D , которые применяются к кортежным значениям вообще. Вотпример:

VAR NADDR1 TUPLE { NAME NAME,
                   ADDR TUPLE { STREET CHAR,
                                CITY   CHAR,
                                STATE  CHAR,
                                ZIP    CHAR } } ;

Важное преимущество схемы именования типов кортежей, предписанной в Манифесте, состоит в том, что она облегчает задачу вывода типа результата произвольного кортежного выражения. Например, рассмотрим следующее кортежное выражение (проекцию кортежа):

NADDR2 { NAME, ZIP }

Это конкретное выражение вычисляет кортеж, который порождается из текущего значения NADDR2 путем “проецирования на все, кроме” атрибутовSTREET , CITY и STATE . И кортежный тип этого порожденного кортежа есть в точности

TUPLE { NAME NAME, ZIP CHAR }

Рассмотрим следующие кортежные типы:

TUPLE { NAME NAME, ADDR TUPLE { STREET CHAR, CITY CHAR,
                                STATE   CHAR, ZIP    CHAR } }

TUPLE { NAME NAME, STREET CHAR, CITY CHAR,
                   STATE   CHAR, ZIP    CHAR }

Будем называть эти два типа TT 1 и TT 2 соответственно. Пусть теперь NADDR 1 и NADDR 2 являются переменными кортежа типов TT 1 и TT 2 , соответственно. Тогда:

  • Выражение

    NADDR2 WRAP { STREET, CITY, STATE, ZIP } AS ADDR

    принимает текущее значение NADDR 2 и “обволакивает” компоненты STREET , CITY , STATE и ZIP этого значения, производя единственный компонент ADDR с кортежным значением. Результат выражения принадлежит, таким образом, типу TT 1 , и тогда (например) допустимо такое присвоение:

    NADDR1  :=  NADDR2 WRAP { STREET, CITY, STATE, ZIP } AS ADDR ;

  • Выражение

    NADDR1 UNWRAP ADDR

    принимает текущее значение NADDR1 и “разворачивает” компонент ADDR (с кортежным значением) этого значения, производя четыре скалярных компонента STREET , CITY , STATE и ZIP . Результат выражения принадлежит, таким образом, типу TT 2 , и тогда допустимо (например) такое присваивание:

NADDR2  :=  NADDR1 UNWRAP ADDR ;

Все, что говорилось выше по поводу кортежных типов, с небольшими коррективами применимо к типам отношений, и мы не будем повторяться. Остановимся только на двух дополнительных операциях – GROUP и UNGROUP . Рассмотрим следующие типы отношения:

RELATION { S# S#, PQ RELATION { P# P#, QTY QTY } … }

RELATION { S# S#, P# P#, QTY QTY }

Назовем эти два типа отношения RT 1 и RT 2 соответственно. Пусть теперь SPQ 1 и SPQ 2 – это relvar типов RT 1 и RT 2 соответственно. Тогда:

  • Выражение s

    SPQ2 GROUP { P#, QTY } AS PQ

    (которое можно было бы прочитать как “сгруппировать SPQ 2 по S # ”, гдеS # –единственный атрибут SPQ 2 , не упомянутый в спецификации GROUP ) вырабатывает отношение, определяемое следующим образом. Во-первых, заголовок выглядит следующим образом:

    { S # S #, PQ RELATION { P # P #, QTY QTY } }

    Во-вторых, тело включает ровно по одному кортежу для каждого уникального значения S # в SPQ 2 (и не содержит никаких других кортежей). Каждый кортеж этого тела состоит из соответствующего значения S # (скажем, s ) и значения PQ (скажем, pq ), получаемого следующим образом:

    • Во-первых, каждый кортеж SPQ 2 заменяется на кортеж (скажем, x ), в котором компоненты P # и QTY обернуты в компонент (скажем, y ) с кортежными значениями.
    • Компоненты y всех таких кортежей x , у которых значение S # равно s , “группируются” в отношение pq , и тем самым генерируется результирующий кортеж со значением S #, равным s , и значением PQ , равным pq

    Таким образом, общий результат относится к типу RT1, и поэтому (например) допустимо следующее присваивание:

    SPQ1  :=  SPQ2 GROUP { P#, QTY } AS PQ ;

  • Выражение

    SPQ 1 UNGROUP PQ

    производит отношение, определяемое следующим образом. Во-первых, заголовок выглядит следующим образом:

    { S# S#, P# P#, QTY QTY }

    Во-вторых, тело содержит в точности по одному кортежу для каждой комбинации кортежа в SPQ 1 и кортежа в значенииPQ внутри этого кортежа SPQ 1 (и не содержит никаких других кортежей). Каждый кортеж в этом теле состоит из соответствующего значения S # (скажем, s ) и значений P # и QTY (скажем, p и q ), получаемых следующим образом:

    • Во-первых, каждый кортеж SPQ 1 заменяется на множество кортежей, по одному такому кортежу (скажем, x ) для каждого кортежа в значении PQ кортежа SPQ 1 . Каждый такой кортеж x содержит компонент S # , равный компоненту S # из соответствующего кортежа SPQ 1 , и компонент с кортежным значением (скажем, y ), равный некоторому кортежу из компонента PQ того же кортежа SPQ 1 .
    • Компоненты y каждого кортежа x , в котором значение S # равняется s , разворачиваются в отдельные компоненты P # и QTY (скажем, p и q ), и тем самым генерируется результирующий кортеж со значением S # , равным s , значением P # , равным p , и значением QTY , равным q .

Таким образом, окончательный результат относится к типу RT 2, и поэтому допустимо следующее присваивание:

SPQ2  :=  SPQ1 UNGROUP PQ ;

Модель наследования

В Третьем манифесте представлена хорошо проработанная, концептуально согласованная модель наследования, базирующаяся на концепции специализации путем ограничения. Д&Д сначала разрабатывают теорию одиночного наследования для скалярных типов, затем развивают ее для множественного наследования скалярных типов и, наконец, обобщают до случая множественного наследования типов кортежей и ограничений. В этой статье мы не можем полностью (хотя бы кратко) описать модель. Ограничимся изложением предписаний (IM -предписаний, IM от Inherinence Model ).

C имволы T и T' используются далее для обозначения пары типов, таких что T' является подтипом T (или, что эквивалентно, T является супертипом для T'). В общем случае эти типы могут быть не только скалярными.

IM-предписание 1

T и T' должны быть типами; то есть каждый из них должен быть именованным множеством значений.

IM-предписание 2

Каждое значение T' должно быть значением T; то есть множество значений, составляющих T', должно быть подмножеством множества значений, составляющих T (другими словами, если значение принадлежит типу T', то оно также должно принадлежать типу T). Более того, если T и T' различны (см. IM-предписания 3 и 4), то должно существовать по крайней мере одно значение, которое принадлежит типу T и не принадлежит типу T'.

IM-предписание 3

T и T' не обязательно должны быть различны; то есть, каждый тип должен быть как подтипом, так и супертипом самого себя.

IM-предписание 4

Если и только если типы T и T' различны, то T' является собственным подтипом T, и T является собственным супертипом T'.

IM-предписание 5

Каждый подтип T' должен быть подтипом T. Каждый супертип T должен быть супертипом T'.

IM-предписание 6

Если и только если T' является собственным подтипом T и не существует типа, который одновременно является собственным супертипом T' и собственным подтипом T, то T' является непосредственным подтипом T, а T является непосредственным супертипом T'. Тип, который не является непосредственным подтипом какого-либо типа, является корневым типом. Тип, который не является непосредственным супертипом какого-либо типа, является листовым типом.

IM-предписание 7

( Вариант, предполагающий только одиночное наследование

Если типы T1 и T2 таковы, что ни один из них не является подтипом другого, то они должны быть непересекающимися; то есть никакое значение не должно одновременно принадлежать типу T1 и типу T2.

IM-предписание 7’

( Вариант, предполагающий множественное наследование )

Если типы T1 и T2 являются различными корневыми типами, то они должны быть непересекающимися; то есть никакое значение не должно одновременно принадлежать типу T1 и типу T2.

IM-предписание 8

( Вариант, предполагающий только одиночное наследование )

Пусть значение v принадлежит скалярному типу T. Если и только если не существует собственный подтип T' типа T такой, что vтакжепринадлежит типу T', то T является наиболее конкретным типом (для) v.

IM-предписание 8’

( Вариант, предполагающий множественное наследование )

Для каждого набора скалярных типов T1, T2, …, Tn (n>0) должен иметься общий подтип T' такой, что заданное значение принадлежит каждому из типов T1, T2, …, Tn, если и только если оно принадлежит типу T'

IM-предписание  9

Пусть скалярная переменная V относится к объявленному типу T. По причине возможности замены значений (см. IM-предписание 16) значение v, присвоенное V , в любой момент времени может принадлежать любому подтипу T' типа T как своему наиболее конкретному типу. Поэтому можно моделироватьV как именованный упорядоченный триплет вида <DT,MST,v>, где:

  1. Именем триплета является имя переменной (в примере это V);
  2. DT является именем объявленного типа переменной V;
  3. MST является именем наиболее конкретного типа – называемого также текущим наиболее конкретным типом – (для)переменной V;
  4. v является значением наиболее конкретного типа – текущим значением (для)переменной V

Обозначения DT(V), MST(V), v(V) используются для ссылок на компоненты DT, MST и v этой модели скалярной переменной V соответственно.

Далее, пусть X - скалярное выражение. Систему обозначений DT(V), MST(V), v(V) можно очевидным образом расширить для ссылок на объявленный тип DT(X), текущий наиболее конкретный тип MST(X) и текущее значение v(X) выражения X соответственно, где “объявленный тип” –  это то, что разъяснялось в RM-предписании 3, и этот тип известен во время компиляции, а “текущий наиболее конкретный тип” и “текущее значение” относятся к результату вычисления X и поэтому в общем случае неизвестны до времени выполнения.

IM-предписание  10

Пусть T - регулярный собственный супертип (см. IM-предписание 20), и пусть T' - непосредственный подтип T. Тогда в определении T' должно специфицироваться ограничение специализации SC, сформулированное в терминах T и такое, что значение типа T должно принадлежать типу T', если и только если оно удовлетворяет ограничению SC. Должно существовать по крайней мере одно значение типа T, которое не удовлетворяет ограничению SC.

IM-предписание  11

Пусть X - выражение. Рассмотрим присваивание

V   :=  X ;

(где V является переменной). DT(X) должно быть подтипом DT(V). Присваивание должно сделать MST(V) равным MST(X), а v(V) - равным v(X).

IM-предписание  12

Рассмотрим сравнение на равенство Y  =  X 

(где Y и X являются выражениями). DT(X) и DT(Y) должны иметь общий супертип. Сравнение должно возвращать true, если MST(Y) равно MST(X) и v(Y) равно v(X), иначе - false.

IM-предписание  13

Пусть rx и ry - отношения с общим атрибутом A, и пусть объявленные типы A в rx и ry - это DT(Ax) и DT(Ay) соответственно. Рассмотрим соединение rx и ry (обязательно по A, по крайней мере, частично). DT(X) и DT(Y) должны иметь общий супертип и, следовательно, обязательно общий наиболее конкретный супертип, скажем T. Тогда объявленным типом A в результате соединения должен быть тип T.

Аналогичные замечания относятся к объединению, пересечению и разности операций. То есть в каждом случае:

  1. Соответствующие атрибуты операндов должны быть такими, что их объявленные типы имеют общий супертип;
  2. Объявленный тип соответствующего атрибута результата должен быть соответствующим наиболее конкретным общим супертипом.

IM-предписание  14

Для каждого типа T должна поддерживаться операция в форме

TREAT_DOWN_AS_T  ( X )

(или ее логический эквивалент), где X является выражением. T должен быть подтипом DT(X) и MST(X) должен быть подтипом T. Такие операции обобщенно называются операциями “TREAT DOWN”; их семантика такова:

  1. Если вызов TREAT DOWN появляется в позиции “источника” (в частности, в правой части присваивания), объявленный тип этого вызова должен быть T, и вызов должен вырабатывать результат, скажем r, с MST(r) равным MST(X) и v(r) равным v(X).
  2. Если вызов TREAT DOWN появляется в позиции “цели” (в частности, в левой части присваивания), этот вызов должен действовать как псевдопеременная, что означает, что он должен реально назначать свой аргумент X (точнее, он должен назначать версию X, для которой DT(X) равно T, но MST(X) и v(X) неизменны). Аргумент X должен быть указан именно как переменная, а не как произвольное выражение.

IM-предписание 15

( Вариант, предполагающий только одиночное наследование )

Для каждого типа T, должна поддерживаться логическая операция вида

IS_T ( X )

(или ее логический эквивалент), где X - выражение. DT(X) должен быть супертипом для T. Эта операция должна возвращать true, если v(X) принадлежит типу T, и false в противном случае.

IM-предписание 15’

( Вариант, предполагающий множественное наследование )

Для каждого типа T, должна поддерживаться логическая операция вида

IS_T ( X )

(или ее логический эквивалент), где X - выражение. DT(X) и T должны иметь общий подтип. Эта операция должна возвращать true, если v(X) принадлежит типу T, и false в противном случае.

IM-предписание 16

Пусть Op - операция только чтения, пусть P - параметр Op, и пусть T - объявленный тип для P. Тогда должно допускаться, чтобы объявленный тип выражения аргумента (и следовательно, тем более, наиболее конкретный тип значения аргумента), соответствующего параметру P в вызове Op, был любым подтипом T' типа T. Другими словами, операция только чтения Op применяется к значениям типа T и поэтому, обязательно, к значениям типа T'Принцип Наследования Операций (Только Чтения). Из этого следует, что такие операции являются полиморфными, поскольку они применимы к значениям нескольких различным типам – Принцип Полиморфизма Операций (Только Чтения). И далее из этого следует, что везде, где допускается значение типа T, должно также допускаться значение любого собственного подтипа TПринцип Возможности Замены (Значений).

IM-предписание 17

Для каждой заданной операции Op должны иметься:

  1. Ровно одна спецификационная сигнатура, состоящая из имени операции Op вместе с объявленными типами параметров в порядке указания параметров (и объявленным типом результата, если он существует), как это указывается потенциальным пользователям Op.
  2. Набор версионных сигнатур, по одной для каждой реализационной версии Op; каждая версионная сигнатура состоит из имени операции Op (и, возможно, имени версии) вместе с объявленными типами параметров в порядке указания параметров (и объявленным типом результата, если он существует), который определяется для этой версии.
  3. Набор сигнатур вызова, по одной для каждой возможной комбинации наиболее конкретных типов аргументов для вызова Op; каждая сигнатура вызова состоит из имени операции Op вместе с соответствующей упорядоченной комбинацией наиболее конкретных типов аргументов.

Если действительно существует несколько версий Op, то все эти версии фактически должны реализовывать одну и ту же семантику.

IM-предписание 18

Пусть Op - операция обновления, и пусть P - параметр Op, который не является предметом обновления. Тогда Op должна вести себя как операция только чтения, насколько это относится к P, и, следовательно, все аспекты IM-предписания 16 должны быть применимы.

IM-предписание 19

Пусть Op - операция обновления, пусть P - параметр Op, который является предметом обновления, и пусть T является объявленным типом для P. Тогда неясно, должно ли допускаться, чтобы объявленный тип (и, следовательно, тем более, текущий наиболее конкретный тип) аргумента-переменной, соответствующего параметру P в некотором вызове Op, был собственным подтипом типа T (в некоторых случаях это должно допускаться, а в некоторых - нет). Из этого следует, что для каждой такой операции обновления Op и для каждого параметра P операции Op, который является предметом обновления, необходимо явно установить, для каких подтипов объявленного типа T параметра P операция Op должна наследоваться – Принцип Наследования Операций (Обновления). (И если операция обновления Op не наследуется таким образом типом T', она не должна наследоваться и никаким подтипом типа T'.) Таким образом, операции обновления должны быть только условно полиморфными – Принцип Полиморфизма Операций (Обновления). Если Op является операцией обновления, P - параметр Op, который является предметом обновления, и T' является таким подтипом объявленного типа T для P, что для T' наследуется Op, то по определению должно быть можно вызывать Op с аргументом-переменной, соответствующим параметру P, когда этот аргумент принадлежит объявленному типу T'Принцип Возможности Замены (Переменных).

IM-предписание 20

Объединенный тип (union type) - это такой тип T, что не существует значения, которое принадлежит типу T и не принадлежит какому-либо собственному подтипу T (то есть не существует такого значения v, что MST(v) есть T). Фиктивный тип (dummy type) - это объединенный тип, который не имеет никакого объявленного возможного представления (и, следовательно, никакого селектора); должно разрешаться, чтобы данный объединенный тип был фиктивным типом, если и только если этот объединенный тип не имеет никакого регулярного непосредственного супертипа (где регулярный тип - это тип, который не является фиктивным типом). Более того,

  1. Концептуально, существует ровно один фиктивный тип, alpha, который содержит все скалярные значения. Тип alpha - это максимальный тип по отношению к каждому скалярному типу; по определению он не имеет никакого объявленного возможного представления и никаких собственных подтипов.
  2. Если и только если мы ослабляем наше допущение об одиночном наследовании, то концептуально также существует ровно один фиктивный тип, omega, который не содержит никаких скалярных значений вообще (то есть является пустым). Тип omega - это минимальный тип по отношению к каждому скалярному типу; по определению он не имеет никакого объявленного возможного представления и никаких собственных подтипов.

IM-предписание 21

Пусть типы T и T' оба являются типами кортежа или оба являются типами отношения с заголовками

{ <A1,T1>,  <A2,T2>, …, <An,Tn> }

{ <A1,T1'>,  <A2,T2'>, …, <An,Tn'> }

соответственно. Тогда тип T' является подтипом типа T (или, эквивалентно, тип T является супертипом типа T'), если и только если для всех i (i = 1, 2, …, n), тип Ti' является подтипом типа Ti (или, эквивалентно, тип Ti является супертипом типа Ti').

IM-предписание 22

Пусть H - заголовок кортежа или заголовок отношения, определенный следующим образом:

{ <A1,T1>,  <A2,T2>, …, <An,Tn> }

Тогда:

a.   кортеж t соответствует заголовку H, если и только если t имеет вид

  { <A1,T1',v1>,  <A2,T2',v2>, …, <An,Tn,vn> }

     где для всех i (i = 1, 2, …, n), тип Ti' является подтипом типа Ti и vi - значение типа Ti'.

c.       отношение r соответствует заголовку H, если и только если r состоит из заголовка и тела, где:

·   Заголовок r имеет вид

   { <A1,T1'>,  <A2,T2'>, …, <An,Tn'> }

   где для всех i (i = 1, 2, …, n), тип Ti' является подтипом типа Ti;

·   Тело r - это множество кортежей, которые все соответствуют   заголовку r.

IM-предписание 23

Пусть все три типа T, T_alpha, и T_omega - это типы кортежей или типы отношений с заголовками

{ <A1,T1>,        <A2,T2>,       …, <An,Tn> }

{ <A1,T1_alpha>,  <A2,T2_alpha>, …, <An,Tn_alpha> }

{ <A1,T1_omega>,  <A2,T2_omega>, …, <An,Tn_omega> }

соответственно. Тогда типы T_alpha и T_omega являются максимальным типом по отношению к типу T и минимальным типом по отношению к типу T соответственно, если и только если для всех i (i = 1, 2, …, n) тип Ti_alpha является максимальным типом по отношению к типу Ti и Ti_omega является минимальным типом по отношению к типу Ti.

IM-предписание 24

Пусть H - заголовок кортежа или заголовок отношения, определенный следующим образом:

{ <A1,T1>,  <A2,T2>, …, <An,Tn> }

Тогда:

  1. Если t - кортеж, соответствующий H – в том смысле, что t имеет вид

      { <A1,T1',v1>,  <A2,T2',v2>, …, <An,Tn’,vn> }

    где для всех i (i = 1, 2, …, n) тип Ti' является подтипом типа Ti', и vi - это значение типа Ti', то наиболее конкретным типом t является

    TUPLE { <A1 ,MST1>,  <A2, MST2>, …, <An  MSTn> }

    где для всех i (i = 1, 2, …, n) тип MSTi является наиболее конкретным типом значения vi.

  2. Если r - отношение, соответствующее H – в том смысле, что тело r является множеством кортежей, каждый из которых имеет в качестве своего наиболее конкретного типа тип, являющийся подтипом типа TUPLE{H}, и в том смысле, кроме того, что каждый кортеж можно считать без потери общности имеющим вид

    { <A1,T1',v1>,  <A2,T2',v2>, …, <An,Tn’,vn> }

    где для всех i (i = 1, 2, …, n), тип Ti' является подтипом типа Ti и наиболее конкретным типом значения vi (отметим, что разные кортежи в теле r будут в общем случае принадлежать разным наиболее конкретным типам; таким образом, тип Ti' различается для разных кортежей в теле r) – то наиболее конкретным типом r является

    RELATION { <A1, MST1>,  <A2, MST2>, …, <An, MSTn> }

    где для всех i (i = 1, 2, …, n), тип MSTi является наиболее конкретным общим супертипом этих наиболее конкретных типов Ti', взятых для всех кортежей в теле r.

IM-предписание 25

Пусть переменная (кортежа или отношения) V имеет объявленный тип T, и пусть заголовок T имеет атрибуты A1,A2, …, An. Тогда можно моделировать V как множество именованных упорядоченных триплетов вида <DTi,MSTi,vi>, где:

  • Имя каждой тройки является именем соответствующего атрибута.
  • DTi является именем объявленного типа атрибута Ai.
  • MSTi является именем наиболее конкретного типа – называемого также как текущим наиболее конкретным типом – (для) атрибута Ai. (Если V - переменная отношения, то наиболее конкретный тип Ai определяется как наиболее конкретный общий супертип наиболее конкретных типов m значений в vi – см. объяснение vi ниже.)
  • Если V - переменная кортежа, то vi - это значение наиболее конкретного типа MSTiтекущее значение (для) атрибута Ai. Если V - переменная отношения, то пусть тело текущего значения V состоит из m кортежей; пометим эти кортежи (в некоторой произвольной последовательности) как “tuple 1”, “tuple 2”, … “tuple m”; тогда vi является последовательностью из m значений (не обязательно различных), являющихся значениями Ai из tuple 1, tuple 2, … tuple m (в таком порядке); отметим, что все эти значения принадлежат типу MSTi.

Обозначения DT(Ai), MST(Ai), v(Ai) используются для ссылок на компоненты DTi, MSTi, vi соответственно атрибута Ai этой модели переменной кортежа или отношения V. Мы также используем обозначения DT(V), MST(V), для ссылки на объявленный тип целиком, текущий наиболее конкретный тип целиком и текущее значение целиком соответственно переменной кортежа или отношения V. Отметим, что фактически MSTi(Ai) подразумевается v(Ai), и MST(V) подразумевается v(V).

Пусть теперь X - выражение кортежей или отношений. Только что введенные обозначения Dti(V), MSTi(V),vi(V) можно очевидным образом расширить для ссылки на объявленный тип Dti(X), текущий наиболее конкретный тип MSTi(X)и текущее значение vi(X) соответственно компонентов Dti, MSTi, vi атрибута Ai выражения кортежей или отношений X. – где “объявленный тип” - это то, что объяснялось в RM-предписаниях 12 и 13; и этот тип известен во время компиляции, а “текущий наиболее конкретный тип” и “текущее значение” относятся к результату вычисления X и в общем случае неизвестны до времени выполнения.

[Назад] [Оглавление] [Вперед]

Бесплатный конструктор сайтов и Landing Page

Хостинг с DDoS защитой от 2.5$ + Бесплатный SSL и Домен

SSD VPS в Нидерландах под различные задачи от 2.6$

✅ Дешевый VPS-хостинг на AMD EPYC: 1vCore, 3GB DDR4, 15GB NVMe всего за €3,50!

🔥 Anti-DDoS защита 12 Тбит/с!

VPS в России, Европе и США

Бесплатная поддержка и администрирование

Оплата российскими и международными картами

🔥 VPS до 5.7 ГГц под любые задачи с AntiDDoS в 7 локациях

💸 Гифткод CITFORUM (250р на баланс) и попробуйте уже сейчас!

🛒 Скидка 15% на первый платеж (в течение 24ч)

Новости мира IT:

Архив новостей

IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

Информация для рекламодателей PR-акции, размещение рекламы — adv@citforum.ru,
тел. +7 495 7861149
Пресс-релизы — pr@citforum.ru
Обратная связь
Информация для авторов
Rambler's Top100 TopList This Web server launched on February 24, 1997
Copyright © 1997-2000 CIT, © 2001-2019 CIT Forum
Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Подробнее...