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

Cdo для класса set (ref(emp))

Рис. 24.4. Пример экземпляров объектов классов DEPT и ЕМР

Теперь рассмотрим объект DEPT, расположенный в центре рисунка с идентификато­ром (OID) ddd, который содержит перечисленные ниже объекты.

  • Неизменяемый объект ' D01' (символьная строка) в открытой переменной экземп­ляра DEPTi

  • Неизменяемый объект 'Mktg' (другая символьная строка) в открытой переменной экземпляра DNAMEt

  • Неизменяемый объект '$1 ООО ООО' (другая символьная строка) определенного пользователем класса MONEY в открытой переменной экземпляра BUDGET

  • Идентификатор еее изменяемого объекта определенного пользователем класса ЕМР в открытой переменной экземпляра MGR (это идентификатор объекта, пред­ставляющего менеджера отдела)

  • Идентификатор sss изменяемого объекта определенного пользователем класса SET(REFjEMP)) в открытой переменной экземпляра EMPS, которая подробнее опи­сана ниже

  • Две закрытые переменные экземпляра, содержащие идентификатор (OID) ddd объекта DEPT и идентификатор соответствующего объекта, определяющего класс

Объект с идентификатором sss состоит из набора идентификаторов индивидуальных (изменяемых) объектов класса ЕМР, а также обычных закрытых переменных экземпляра.

На рис. 24.4 экземпляры объектов представлены в том виде, в котором они реально существуют, т.е. на рисунке отображается компонент структуры данных "объектной модели", что позволяет яснее представить саму объектную модель. Обычно в книгах или документации такие диаграммы не используются; вместо этого данные представляются так, как на рис. 24.5, на более высоком уровне абстракции, что, как принято считать, об­легчает понимание объектной модели.

DEPT:

DEPT#: D01 DNAME: Mktg

BUDGET: MGR: I

$1 000 000

EMP#: E001 ENAME: Smith

SALARY: POSITION:

$50 000

job

EMPS:

I

EMP#: E001 ENAME: Smith

SALARY: POSITION:

$50 000

job

Puc. 24.5. Пример представления экземпляров объектов DEPT и ЕМР в соответствии с ие­рархией их вложения

Приведенная на рис. 24.5 схема в большей степени согласуется с интерпретацией на основе иерархии вложения. Однако в ней остается скрытым важный факт; в объектах часто содержатся не собственно другие объекты, а их идентификаторы. Например, со­гласно рис. 24.5 можно предположить, что объект класса DEPT для отдела с номером 'D01' содержит два экземпляра объекта класса ЕМР для сотрудника с номером 'Е001' (при этом, помимо всего прочего, может получиться, что сотрудник с номером ' Е001' получает две различные зарплаты). Такая ситуация может привести к путанице, поэтому предпочтение следует отдавать схемам, подобным приведенной на рис. 24.4.

В дополнение к этому следует заметить, что реальные объектные определения дан­ных способствуют возникновению запутанных ситуаций, поскольку переменные экземп­ляра в них обычно определяются не на основе "ссылок" (как в приведенных выше выра­жениях с использованием гипотетического синтаксиса), а на основе непосредственного отображения иерархии вложения. Например, переменные экземпляра EMPS в объектном классе DEPT обычно определяются не как REF(SET(REF(EMP))), а в более краткой форме: SET (ЕМР). Несмотря на некоторую громоздкость полной записи, мы все же предпочитаем наш стиль, как более ясный и точный.

Следует отметить, что вся прежняя критика иерархического подхода (например, ие­рархии вложения, воплощенной в СУБД IMS) в основном относилась именно к иерархи­ям вложения. Подробное рассмотрение данного вопроса заняло бы слишком много места, поэтому достаточно сказать, что основным аргументом такой критики было от­сутствие симметрии. В частности, иерархии не совсем удобны для представления от­ношений типа "многие ко многим". Например, для рассматриваемого ранее отношения поставщиков и деталей может возникнуть вопрос, содержатся ли объекты-поставщики в объектах-деталях или наоборот. А может, верно и то, и другое? А что можно сказать об отношениях поставщиков, деталей и проектов?

Действительно, подобных вопросов больше, чем можно было бы предположить. С одной стороны, как мы убедились, объекты представляют собой иерархию, и к ним также относятся привычные критические замечания относительно иерархий. А с другой сторо­ны, как явствует из рис. 24.4, такие объекты на самом деле образуют не иерархию, а кортежи с перечисленными ниже компонентами.

  1. Неизменяемые "подобъекты", т.е. самоидентифицируемые значения, такие как це­лые числа и денежные суммы.

  2. Идентификаторы изменяемых "подобъектов", т.е. ссылки или указатели на другие (возможно, совместно используемые) изменяемые объекты.

  3. Множества, списки, массивы и т.д. объектов, перечисленных в пп. 1, 2 и в этом пункте.

К этому списку следует также добавить скрытые идентификаторы объектов, иденти­фикаторы объектов, определяющих классы, и т.д. В частности, обратите внимание на п. 3: обычно объектные системы поддерживают несколько "коллекций" генераторов типов (SET, LIST, ARRAY и др.), но обычно не поддерживают тип RELATION (отношение). Такие генераторы могут сочетаться сколь угодно сложно. Например, массив списков па­кетов массивов указателей на целые переменные может составлять при определенных условиях отдельный изменяемый объект. В следующем подразделе мы продолжим об­суждение этого вопроса.

Еще раз об идентификаторе объекта

Чтобы сослаться на объект или идентифицировать его, в современных реляционных СУБД обычно используются ключи, определяемые и управляемые пользователями (далее для краткости будем называть их пользовательскими ключами), хотя, как нам из­вестно из главы 3, в реляционных базах данных указатели наподобие идентификаторов объектов фактически намеренно запрещены. Также хорошо известно, что применение пользовательских ключей сопряжено с некоторыми проблемами. Эти проблемы доста­точно подробно рассматриваются в [13.10] и [13.16], где сделан вывод, что реляционные СУБД, по крайней мере в качестве альтернативы, должны поддерживать и ключи, опре­деляемые системой ("суррогатные"). Аргументы в пользу идентификаторов объектов в объектных системах подобны аргументам в пользу суррогатных ключей в реляционных системах. (Однако их не следует приравнивать друг к другу, поскольку суррогатные ключи — это доступные пользователю значения, а идентификаторы объектов — это ад­реса или указатели, которые, по крайней мере концептуально, от пользователя скрыты. В [24.19] широко обсуждается это различие и другие связанные с ним вопросы.)

Здесь следует отметить некоторые важные моменты.

  1. Необходимо понимать, что, как будет показано в разделе 24.4, наличие идентифи­каторов объектов не позволяет полностью исключить применение пользователь­ских ключей. Точнее, пользовательские ключи необходимы для общения с внеш­ним миром, хотя внутри базы данных все объекты могут ссылаться один на другой только с помощью идентификаторов объектов.

  2. Что является идентификатором производного объекта, например "соединения" неко­торого объекта класса ЕМР и соответствующего объекта класса DEPT или "проекции" объекта класса DEPT по атрибутам BUDGET и MGR? Это очень важный вопрос для произ­водных объектов, рассмотрение которого мы отложим до раздела 24.5.

  3. Идентификаторы объектов часто служат предметом критических замечаний, вы­званных тем, что объектные системы выглядят, как "модифицированный стандарт CODASYL". Стандарт CODASYL использовался для сетевых систем управления базами данных (например, для СУБД IDMS), которые были созданы до появления реляционного подхода. Использование идентификаторов объектов приводит к низ­коуровневому стилю программирования (см. раздел 24.4.), что очень напоминает устаревший стиль программирования согласно стандарту CODASYL. Кроме того, поскольку идентификаторы объектов являются указателями, часто можно услы­шать, что системы типа CODASYL ближе к объектным системам, чем реляцион­ные, и что реляционные системы основаны на значениях, в то время как объектные системы — на идентичности.

Классы, экземпляры и коллекции

В области объектных систем четко разделяются концепции класса, экземпляра и кол­лекции. Как уже отмечалось, объектный класс является, в основном, типом данных, при­чем он может быть встроенным или определенным пользователем, а также быть сколь угодно сложным7. Каждый класс способен принять сообщение NEW, которое приводит к созданию нового (изменяемого) экземпляра объекта данного класса.

Замечание. Вызываемый этим сообщением метод иногда называют конструкто­ром класса.

Ниже приводится пример такого сообщения, записанного с помощью некоторого ги­потетического синтаксиса.

Е := ЕМР NEW ( 'Е001', 'Smith', MONEY ( 50000 ), POS ) ;

7 Как уже подчеркивалось в разделе 24.2, в некоторых системах используются оба поня­тия— и "тип", и "класс". В этих системах "тип" означает тип, т.е. содержание или сущ­ность понятия, а "класс" означает применение этого понятия, т.е. определенную коллекцию, или иногда реализацию данного типа. В других системах данные термины используются ина­че... Мы же по-прежнему будем употреблять термин "класс" для обозначения типа в том смысле, что и в главе 5.

Здесь программная переменная POS содержит идентификатор некоторого объекта класса JOB, а метод NEW вызывается для создания нового экземпляра класса ЕМР, инициа­лизации его переменных экземпляра заданными значениями, возвращения идентифика­тора нового экземпляра и присвоения его программной переменной Е.

Поскольку одни объекты могут ссылаться на любые другие объекты с помощью идентификаторов, один объект может совместно использоваться несколькими другими объектами. В частности, один и тот же объект может одновременно относиться к не­скольким различным коллекциям объектов. В продолжение рассматриваемого примера приведем еще одно выражение.

CLASS EMP_COLL

PUBLIC ( EMPS REF ( SET ( REF ( EMP ))))... ;

ALL_EMPS := EMP_C0LL NEW ( ) ;

ALL_EMPS ADD ( E ) ; Пояснения

  • Объект класса EMP_COLL содержит одну открытую переменную экземпляра EMPS, зна­чением которой является указатель (идентификатор) на изменяемый объект, значение которого представляет собой набор указателей на отдельные объекты класса ЕМР.

  • ALL_EMPS — это программная переменная, значением которой является идентифи­катор объекта класса EMP_COLL. После выполнения операции присвоения она будет содержать идентификатор объекта, значением которого, в свою очередь, будет идентификатор пустого множества идентификаторов объектов ЕМР.

  • ADD — это метод объектов класса EMP_C0LL. В рассматриваемом примере данный метод применяется для объекта класса, идентификатор которого содержится в программной переменной ALL_EMPS, и предназначается для добавления идентифи­катора объекта ЕМР, который содержится в программной переменной Е, к набору идентификаторов (изначально пустому). Причем идентификатор этого набора со­держится в объекте EMP_COLL, идентификатор которого находится в программной переменной ALL_EMPS.

Рассмотрев приведенную выше последовательность операций, можно заметить, что переменная ALL_EMPS связана с набором объектов ЕМР, который в текущий момент со­держит только один объект, а именно — объект, описывающий сотрудника с номером 'Е001'. (Помимо всего прочего, обратите внимание на то, что необходимо упомянуть значение ключа пользователя в последнем предложении!)

Конечно, в некоторый заданный момент может существовать любое количество раз­ных и, возможно, перекрывающихся "наборов сотрудников", например следующих.

PROGRAMMERS := EMP_COLL NEW ( ) ; PROGRAMMERS ADD ( E ) ;

HIGHLY_PAID := EMP_C0LL NEW ( ) ; HIGHLY_PAID ADD ( E ) ;

Приведенный ниже пример SQL-выражения показывает, что в реляционных системах все может быть организовано совсем иначе.

CREATE TABLE ЕМР ( EMPf ... ,

ENAME ... , SALARY ... , POSITION ...)...;

В этом случае тип и коллекция создаются одновременно, причем сложный тип соот­ветствует заголовку таблицы, а исходно пустая коллекция соответствует содержанию таблицы. Точно так же приведенное ниже SQL-выражение позволяет одновременно соз­дать отдельную строку ЕМР и добавить ее к коллекции ЕМР.

INSERT INTO ЕМР ( ... ) VALUES (...);

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

  1. Отдельный "объект" класса ЕМР не может существовать, не являясь частью некото­рой "коллекции", фактически — какой-то единственной "коллекции" (подробности приведены ниже).

  2. Не существует непосредственного способа создания двух различных "коллекций" объектов одного и того же "класса" ЕМР (подробности приведены ниже).

  3. Не существует непосредственного способа совместного использования одного и того же "объекта" в нескольких "коллекциях" "объектов" ЕМР (подробности приве­дены ниже).

Именно такие претензии иногда можно услышать, однако они не выдерживают серь­езной критики. Во-первых, для достижения равноценного эффекта в каждом случае мо­жет применяться реляционный метод использования внешнего ключа. Например, можно определить две базовые таблицы, PROGRAMMERS (программисты) и HIGHLY_PAID (высокооплачиваемые), каждая из которых состоит из номеров соответствующих со­трудников. Во-вторых, что еще важнее, для достижения того же эффекта может быть применен реляционный метод с использованием представлений. Например, таблицы PROGRAMMERS и HIGHLY_PAID можно определить как представления, созданные на основе базовой таблицы ЕМР.

CREATE VIEW PROGRAMMERS

AS SELECT EMP#, ENAME, SALARY, POSITION FROM EMP

WHERE POSITION = 'Programmer' ;

CREATE VIEW HIGHLY_PAID

AS SELECT EMPi, ENAME, SALARY, POSITION FROM EMP

WHERE SALARY > <некоторое значение, например 75 00Q> ;

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

Завершая эту тему, следует упомянуть об одной интересной параллели, существую­щей между изменяемыми объектами объектных систем и явно заданными динамиче­скими переменными некоторых языков программирования (например, базовыми пере­менными языка PL/I). Как и в случае изменяемых объектов данного класса, может суще­ствовать любое количество отдельных явных динамических переменных данного типа, память для которых выделяется во время выполнения явно заданными указаниями про­граммиста. Более того, эти отдельные переменные, как и отдельные изменяемые объек­ты, не имеют имен, а потому на них можно ссылаться только с помощью указателей. Например, в языке PL/I можно записать такую последовательность выражений.

DCL XYZ INTEGER BASED ; /* XYZ - базовая переменная */ DCL Р POINTER ; /* Р - указатель */

ALLOCATE XYZ SET { Р ); /* создание нового экземпляра XYZ, */

/* на который указывает Р */

Р -> XYZ = 3 ; /* присвоение значения 3 экземпляру */

/* XYZ, на который указывает Р */

Этот записанный на языке PL/I код очень похож на рассмотренный ранее объектный код. В частности, объявление базовой переменной подобно объявлению класса объектов, а операция ALLOCATE — созданию нового экземпляра объекта этого класса. Таким обра­зом, основная причина, по которой в объектной модели необходимы идентификаторы, заключается в том, что те объекты, которые они идентифицируют, не обладают уникаль­ными именами (точно так же, как базовые переменные в языке PL/I).

Иерархии классов

Описание концепций объектного подхода было бы неполным без рассмотрения ие­рархий классов (их не следует путать с иерархиями вложения). Однако объектная кон­цепция "иерархии классов", в сущности, является тем же, что и концепция иерархии ти­пов, рассмотренная в главе 19. Следовательно, здесь можно ограничиться несколькими краткими определениями (большей частью это перефразированные выражения из главы 19) и соответствующими примерами.

Замечание. Напомним, что в объектном мире, как и в остальных случаях, все еще нет полной согласованности относительно концепции абстрактной модели наследова­ния, поэтому различные системы наследования существенно отличаются одна от дру­гой на уровне деталей.

Начнем с того, что объектный класс Y является подклассом класса X, а объектный класс X — суперклассом объектного класса Y тогда и только тогда, когда каждый объект класса Y обязательно является и объектом класса X (т.е. "Y ISA X"). В этом случае объ­ект класса Y наследует переменные экземпляра и методы класса X. Наследование пере­менных экземпляра обычно называют наследованием структуры, а наследование мето­дов — наследованием поведения. В истинно объектных системах не может быть насле­дования структуры, а возможно лишь наследование поведения (по крайней мере для ска­ляров и инкапсулированных объектов), поскольку нет структуры для наследования (т.е. пользователю никакая структура не видна). Однако на практике объектные системы обычно несовершенны и в какой-то мере поддерживают структурное наследование, ко­торое, подчеркиваем, означает наследование открытых переменных экземпляра.

Если класс Y является подклассом класса X, то пользователю предоставляется воз­можность применять объект класса Y вместо объекта класса X везде, где это допустимо, т.е. в качестве аргумента различных методов. Этот принцип называется принципом подстановки и весьма полезен для повторного использования кода. Однако, посколь­ку в объектных системах не всегда четко прослеживается разница между значениями и переменными (т.е. между неизменяемыми и изменяемыми объектами), возникают про­блемы различения значения и возможного замещения переменной (этот вопрос обсужда­ется в главе 19). Возможность применять один и тот же метод для объектов класса X и класса Y называется полиморфизмом.

Обычно объектные системы поставляются с определенной встроенной иерархией классов. Например, в системе OPAL (см. раздел 24.4) каждый класс рассматривается как подкласс некоторого уровня встроенного класса OBJECT (поскольку "все является объек­тами"). Встроенные подклассы класса OBJECT включают классы BOOLEAN, CHAR, INTEGER, COLLECTION и др. Класс COLLECTION, в свою очередь, включает подкласс BAG, а класс BAG содержит класс SET и т.д. и т.п.

Наконец, в некоторых системах, кроме одиночного наследования, в той или иной форме поддерживается множественное наследование. Однако автору не известно ни од­ной системы, которая поддерживала бы наследование кортежей или отношений (как одиночное, так и множественное) в смысле, который подразумевался в [3.3].

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