
- •Введение
- •1. Достоинства и недостатки реляционной и объектной моделей Задачи, недоступные для реляционного подхода
- •Задачи, недоступные для объектного подхода
- •Задачи, недоступные обеим моделям
- •2. Реализация объектного подхода в oracle
- •2.1. Хранение объектов в столбцах реляционных таблиц
- •2.2. Создание таблицы объектов
- •2.3. Ссылки на объект
- •2.4. Методы объектов
- •2.5. Конструкторы
- •2.6. Статические методы
- •2.7. Методы сравнения
- •2.8. Объектные представления
- •3. Реализация механизма наследования объектов в oracle
- •3.1. Особенности наследования объектов в oracle
- •3.2. Абстрактные объекты
- •4. Реализация полиморфизма в субд oracle
- •4.1. Полиморфизм типов
- •4.2. Расширение и сужение объектных типов
- •4.3. Оператор is of
- •4.4. Виртуальные методы
4. Реализация полиморфизма в субд oracle
Под полиморфизмом в ORACLE понимается возможность использования свойства подстановочности (substitutability) и динамической диспетчеризации методов (Dynamic Method Dispatch), или иными словами, виртуальных методов.
4.1. Полиморфизм типов
Подстановочность – это основная характеристика полиморфизма типов (type polymorphism), которая позволяет использовать значение некоторого подтипа там, где ожидается значение супертипа.
Для понимания уровня реализации полиморфизма типов в объектной модели СУБД ORACLE рассмотрим следующий пример.
DROP TABLE Deps;
DROP TABLE Employees;
DROP SEQUENCE Employees_seq;
-- создадим таблицу для хранения информации об отделах и наполним ее данными:
CREATE TABLE Deps OF department_typ;
INSERT INTO Deps VALUES(1, ‘Отдел продаж’);
INSERT INTO Deps VALUES(2, ‘Отдел закупок’);
INSERT INTO Deps VALUES(3, ‘Отдел кадров’);
Нам также понадобится таблица для хранения информации о сотрудниках и последовательность для генерации значений первичных ключей таблицы:
CREATE TABLE Employees(
emp_id NUMBER,
employee employee_typ
);
CREATE SEQUENCE Employees_seq;
Рассмотрим, каким образом можно хранить данные о разных сотрудниках в одной таблице:
-- добавление босса:
INSERT INTO Employees VALUES(Employees_seq.NEXTVAL, boss_typ(‘Петр Иванович Сидоров’, to_date(’12.03.2004’,’dd.mm.yyyy’)));
-- добавление менеджера по продаже:
INSERT INTO Employees VALUES(Employees_seq.NEXTVAL, sales_manager_typ( ‘Вася’, to_date(’12.03.2004’,’dd.mm.yyyy’), department_typ(1,’Отдел продаж’)));
-- выборка перечня сотрудников предприятия:
SELECT * FROM Employees;
Здесь нужно обратить внимание на полезность объявления типа employee_typ как абстрактного. В противном случае была бы разрешена следующая не вполне логичная команда:
INSERT INTO Employees VALUES(Employees_seq.NEXTVAL, employee_typ(‘Дядя Петя’,sysdate));
В ответ на попытку выполнить эту команду СУБД вполне резонно заметит, что нельзя создавать экземпляры объектов абстрактных типов. С точки зрения поддержания целостности базы данных это является правильным (если существует бизнес-правило, что все сотрудники должны относиться к какому-то отделу или являться начальниками).
4.2. Расширение и сужение объектных типов
Рассмотрим две концепции: расширение и сужение, очень полезные при работе с объектами в иерархии типов. Вот их определение:
Расширение – это присвоение, в котором объявленный тип источника является более конкретным, чем объявленный тип места назначения (например, присвоение переменной типа sales_manager_typ значения типа employee_typ).
Сужение – это присвоение, в котором объявленный тип источника является более общим, чем объявленный тип места назначения (например, присвоение переменной типа employee_typ значения переменной sales_manager_typ).
Примеры неявного расширения были рассмотрены ранее (присвоение столбцу типа employee_typ значений типов boss_typ и sales_manager_typ). Рассмотрим, как выполняется более сложный шаг – сужение.
ORACLE предоставляет специальную функцию TREAT, которая позволяет выполнять операцию сужения. Функция TREAT явно изменяет объявленный тип источника в присваивании на более специализированный тип (подтип) в иерархии места назначения. Без использования этой функции нельзя сослаться на специфичные для подтипа атрибуты и методы.
-- общий синтаксис функции:
TREAT (<object_instance> AS <object_type>)
где <object_instance> – это значение столбца или строки коллекции данного конкретного супертипа в объектной иерархии, а <object_type> – это подтип в этой иерархии.
-- например, можно выполнить запрос:
SELECT e.employee.Name FROM Employees e;
-- не удастся выполнить следующий запрос, поскольку свойство Dep есть только
-- у типа sales_manager_typ и его подтипов:
SELECT e.employee.Dep.Caption FROM Employees;
-- для выполнения предыдущей задачи необходимо выполнить запрос:
SELECT TREAT(employee as sales_manager_typ).Dep.Caption FROM Employees;
Для объектов отличных от sales_manager_typ функция TREAT вернет значение NULL.