[Содержание_документа] [Конец_документа]

[Выше] [Начало_этой_части] [Конец_этой_части] [Далее]

===========================================

Глава 2 – Объектная модель

Глава содержит следующие темы:

 Обращение к объекту

 Классы

 Наследование

 Компиляция

Как объектно-ориентированная система, Cache предлагает наиболее близкий к реальному миру способ моделирования. Более того, Cache расширяет стандартную объектно-ориентированную модель новыми мощными возможностями. Эта глава описывает объекты и то, как они связаны с окружающим миром. В главе 3, "Спецификация класса", продолжается обсуждение объектной модели Cache и описываются внутренние элементы и структуры классов Cache.

Объектные модели Cache имеют следующие особенности:

 Основные элементы – объектные классы (object classes) и классы-типы_данных (data types classes, известные также как литералы).

 Объекты могут иметь поведение, предопределеное Cache или созданное разработчиком приложения.

 Хранимые объекты (persistent objects) могут быть автоматически сохранены в базе данных Cache.

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

Cache также включает классы-типы_данных. Эти классы (иногда называемые литеральными классами, со значениями, называемыми литералами) описывают значения простых свойств, имеющихся у объектных классов. В отличие от объектных классов, классы-типы_данных не содержат свойств, и они для таких классов не определяются. Экземпляры класса-типа_данных всегда существуют только неявно. Например, целое число 5 всегда существует; оно никогда не должно создаваться, хотя объект Invoice должен быть создан.

Обращение к объекту

В Cache объекты могут храниться на диске или в памяти. Дисковый объект – это такой объект, который хранится в базе данных; объект в памяти – это такой объект, который загружен из базы данных и которым можно манипулировать. К объекту можно обратиться двумя способами (в зависимости от того, где он находится - загружен в память или хранится на диске):

 OREF (объектная ссылка)

 OID (идентификатор объекта)

 

OREF относится к версии объекта в памяти. Каждый раз, когда объект загружается память, ему присваивается уникальная в данный момент времени ссылка OREF.

OID относится к дисковой версии объекта. OID уникально идентифицирует хранимый объект, который хранится в базе данных. Как только объект получил значение OID, это значение не меняется.

Как правило, методы, унаследованные от класса %Persistent, и методы, унаследованные от класса %RegisteredObject, устанавливают OREF объекта. См. следующий раздел для получения дополнительной информации о классах %RegisteredObject и %Persistent.

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

Классы

Cache содержит большую иерархию поддерживаемых объектов. Этот раздел начинается с краткого обзора иерархии объектов и часто используемых классов. Затем будет дана более детальная информация о следующих классах:

  Регистрируемые классы (Registered)

 Хранимые классы (Persistent)

 Встраиваемые классы (Embeddable)

 Нерегистрируемые классы (Non-Registered)

 Классы-типы_данных (Data Type)

В Cache можно использовать следующие классы:

 

Классы Делятся на классы-типы_данных (Data Type Classes) и объектные классы (Object Classes). Классы-типы_данных представляют литеральные значения (например, строки, целые числа и даты); см. главу 5, "Типы данных" для получения детальной информации о классах-типах_данных. Большинство объектных классов - подклассы системного класса, называемого %RegisteredObject, который автоматически обеспечивает многие методы объекта. Такой класс известен как регистрируемый класс (Registered Class). Класс, который не получен из %RegisteredObject, называется нерегистрируемым классом (Non-Registered Class). Так как нерегистрируемые классы поддерживают только базовые методы, в приложении эти классы следует обеспечить дополнительными методами.

Регистрируемый объект имеет большой набор заданных по умолчанию методов, которые обеспечивают:

 Автоматическое распределение системной памяти для его свойств.

 Автоматическое создание ссылки на объект.

 Поддержку полиморфизма.

Регистрируемый - это переходный объект, поскольку его заданные по умолчанию методы не включают функциональные возможности хранения. Способ хранения задает иерархию: это - классы %Persistent и %SerialObject. которые являются подклассами %RegisteredObject.

Хранимый объект, унаследованный от %Persistent, может быть независимо сохранен в базе данных с назначением ему OID. Встраиваемый объект, унаследованный от %SerialObject, может быть сохранен в базе данных только как часть хранимого объекта; класс %SerialObject также позволяет создать единственную строку, описывающую его состояние. Классы %SerialObject и %Persistent поддерживают свизлинг (swizzling).

Регистрируемые классы (классы Registered)

Большинство приложений использует хранимые классы и встраиваемые классы, напрямую унаследованные от системного класса %RegisteredObject. Эта группа классов называется регистрируемыми классами. Объекты регистрируемых классов имеют полный набор встроенных методов для управления их поведением в памяти.

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

Объект, который наследуется от %RegisteredObject, не может иметь в качестве OREF пустую строку (NULL OREF или ("")). Такое значение может возникнуть только тогда, когда встроенный метод %New() класса %RegisteredObject не может создать экземпляр класса.

Регистрируемые объекты используют для хранения состояния системную распределенную память. Они поддерживают полиморфизм.

Хранимые классы (классы Persistent)

Экземпляры классов, унаследованные от %Persistent, известны как хранимые объекты; эти объекты имеют модификатор Persistent. Объект с модификатором Persistent может сохранять себя в базе данных.

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

Когда хранимый объект используется как атрибут, это понимается как "ссылка к хранимому объекту". Например, если Doctor – хранимый объект, то можно определить атрибут, используя Doctor как его тип:

ATTRIBUTE TheDoc {TYPE = Doctor;}

и тогда атрибут TheDoc является атрибутом-ссылкой.

Встраиваемые классы (классы Embeddable)

Экземпляры классов, унаследованные от %SerialObject, известны как встраиваемые объекты. Эти объекты могут независимо существовать в памяти, но, когда их сохраняют в базе данных, они могут существовать только как часть хранимого объекта (объекта-контейнера).

Класс %SerialObject – подкласс класса %Registered – обеспечивает:

 Способность формировать одну строку, отражающую состояние объекта (создание такой строки известно как сериализация (Serializing) объекта - получение встраиваемой строки).

 Способность поддерживать свизлинг, используя встраиваемую строку. Подобно объектам Persistent, объект %SerialObject может быть определен как атрибут типа, но дисковое поведение таких объектов отличается от поведения объектов Persistent. Когда объект %SerialObject используется как атрибут, он известен как встраиваемый (Embeddable) объект.

Встраиваемые объекты имеют различное представление в памяти и на диске:

 В памяти: встраиваемый объект представлен как отдельный самостоятельный объект и неотличим от другого объекта. Значение атрибута встраиваемого объекта в памяти – OREF, которая относится к представлению объекта в памяти.

 На диске: атрибут встраиваемого объекта хранится как часть содержащего его объекта. Объект не имеет своего OID и на него не могут ссылаться другие объекты. Значения свойств встраиваемого объекта преобразованы во встраиваемую строку и хранятся наряду со всеми другими объектными атрибутами.

Следующая диаграмма иллюстрирует существование встраиваемого объекта в памяти и на диске:

Когда создается новый объект, содержащий встраиваемый объект, метод %New() автоматически создает экземпляр встраиваемого объекта в памяти.

Например, рассмотрим класс Address:

CLASS Address

{

SUPER = %SerialObject;

ATTRIBUTE Street { TYPE = %String(MAXLEN=80); }

ATTRIBUTE City { TYPE = %String(MINLEN=3); }

ATTRIBUTE State { TYPE = %String(MINLEN=2); }

}

После определения класс Address может использоваться как атрибут встраиваемого объекта для хранимого объектного класса Patient:

CLASS Patient

{

SUPER = %Persistent;

PERSISTENT;

ATTRIBUTE Name { TYPE = %String; }

ATTRIBUTE Home { TYPE = Address; }

}

Нерегистрируемые классы (классы Non-Registered)

Класс, который не наследуется от класса %RegisteredObject, называется нерегистрируемым (Non-registered) классом. Нерегистрируемые классы часто упрощены и требуют специфического программирования. Существенно, что нужно реализовать обеспечение значения OREF для такого объекта. Поскольку система не назначает и не регистрирует это значение, нерегистрируемые классы имеют несколько ограничений:

 Система не распределяет память для содержимого объекта.

 Свизлинг автоматически не поддерживается.

 Полиморфизм не поддерживается.

 Требуется явное объявление типа класса для переменной, которая используется для обращения к объекту (например, pat в pat.name).

Рассмотрим пример, иллюстрирующий, как объект Patient может быть определен для регистрируемого класса и нерегистрируемого класса. Использование нерегистрируемого класса означает, что каждое из свойств объекта Patient – это глобальная ссылка, заменяющая OREF и OID, необходимые для обращения к объекту Patient. Таким образом, если переменная pat содержит значение "12345", конструкция

Set n=pat.name

может быть эквивалентна следующей:

Set n=$LIST(^patient(pat,1),2)

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

С другой стороны, при управлении хранимыми объектами, обычно, нужно загрузить объект в память, выполнить требуемые действия, а затем – сохранить объект. Эти функциональные возможности обеспечиваются хранимыми объектами, унаследованными от класса %RegisteredObject. В этом случае можно написать:

Set pat=##class(Patient).%Open(oid)

Эта конструкция загружает объект Patient с OID oid в назначенную системой область памяти и сохраняет ссылку (OREF) на него в переменной pat.

Если объект находится в памяти, к нему можно обратиться, используя синтаксис:

pat.Name

Это позволяет легко управлять объектом с помощью, например, такого кода:

Set pat.Name="Smith,Juan"

Сохранить объект в базе данных можно, применив такую запись:

Set x=pat.%Save()

Эта команда сохраняет объект Patient и возвращает результат операции: 1, если сохранение выполнено успешно, иначе – 0.

Классы-типы_данных (классы Data Type)

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

Класс-тип_данных – это класс с модификатором класса DATATYPE, обладающий определенным набором методов – интерфейс типа данных. Этот интерфейс включает множество операций, предназначенных для взаимодействия с SQL и проверки на принадлежность типу. Классы-типы_данных не имеют свойств.

Например, Класс Patient (Пациент) может определять атрибут Name (Имя), используя тип данных %String:

CLASS Patient {

ATTRIBUTE Name { TYPE = %String; }

Name существует как свойство определенного объекта Patient. К нему можно обращаться только как к атрибуту объекта:

Set n=pat.Name

Когда объект уничтожен, Name исчезает.

Класс имеет два типа атрибутов: атрибуты-типы_данных и объектные атрибуты. Например, объект Person может иметь свойство DateOfBirth, которое содержит Date (Дату), которая является атрибутом-типом_данных; объект может также иметь свойство Home (Дом), которое содержит Address (Адрес) объекта. Объектный атрибуты может быть встраиваемым объекты или ссылкой на хранимый объект.

Наследование

Объектная модель Cache позволяет проектировать классы с единичным и множественным наследованием, используя модификатор SUPERCLASS. Класс наследует все спецификации его суперклассов, включая свойства, методы, параметры класса, соответствующие модификаторы, параметры и модификаторы унаследованных свойств и методов. За исключением случаев, когда класс имеет модификатор FINAL, подкласс может отменять (но не удалять) унаследованные им компоненты. Для подробной информации о модификаторах см. главу 3, "Спецификация класса".

Кроме наследования классом методов от его суперклассов, свойства класса наследуют дополнительные методы от системных классов, а, в случае атрибута-типа_данных – от класса-типа_данных.

Например, если имеется класс с именем Person (Человек):

CLASS Person

{

SUPER = %Persistent;

PERSISTENT;

ATTRIBUTE Name { TYPE = %String; }

ATTRIBUTE DOB { TYPE = %Date; }

}

из него просто получить новый класс Employee (Служащий):

CLASS Employee

{

SUPER = Person;

PERSISTENT;

ATTRIBUTE Salary { TYPE = %Integer; }

ATTRIBUTE Department { TYPE = %String; }
}

Это определение создает класс Employee как подкласс класса Person. В дополнение к его собственным параметрам, свойствам и методам, класс Employee включает все эти элементы из класса Person.

Подкласс можно использовать в любом месте, где можно использовать его суперкласс. Например, используя вышеупомянутые классы Employee и Person, можно открыть объект Employee и обращаться к нему как к Person:

#class Person x

SET x=##class(Person).%Open(oid)

WRITE x.Name -> "Groucho Marx"

Можно также обращаться к специфическим атрибутам или методам Employee:

WRITE x.Salary 22000

Множественное наследование

При множественном наследовании класс может наследовать методы (поведение) и свойства от нескольких суперклассов. Чтобы установить множественное наследование, следует использовать модификатор SUPER, а затем указать классы, от которых будет выполняться наследование.

Когда класс компилируется, компилятор класса устанавливает значения для элементов класса согласно списку суперклассов; элементы класса – это параметры класса, его методы и свойства, но не модификаторы класса. Если в списке суперклассов имеются элементы с одинаковыми именами, то приоритет имеет последний суперкласс из списка.

Следует обратить внимание, что не выполняется перекрытие модификаторов класса. Для них подкласс наследует только значения модификатора его первого суперкласса.

Например, если класс X наследует от классов A, B, и C, то его определение должно включать:

create class X

{

super = A, B, C;

}

В этом примере значения параметров класса X, его свойства и методы наследуются от класса A (первый перечисленный суперкласс), затем от класса B и, наконец, от класса C. Если класс B имеет элемент класса с таким же именем как член, уже унаследованный от класса A, то производится замена ранее унаследованного члена из класса A на член класса B; аналогичные действия производятся для членов класса C относительно одноименных элементов класса B. Модификаторы класса для класса X наследуются исключительно от класса A.

Компиляция

Спецификация класса Cache компилируется в прикладные программы компилятором классов Cache (Cache Class Compiler). Классы не могут использоваться в приложении до тех пор, пока они не скомпилированы.

Можно определить режим компиляции: компилировать один класс, все зависимые классы (спецификации которых изменялись) или все классы.

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

Когда требуется компиляция всех классов, компилятор класса компилирует все классы библиотеки приложения, даже если класс в библиотеке рабочей области (namespace) приложения не ссылается на них.

===========================================

[Содержание_документа] [Конец_документа]

[Выше] [Начало_этой_части] [Конец_этой_части] [Далее]

===========================================

По вопросам поддержки любых продуктов InterSystems Corporation обращайтесь:

Россия 121019, Москва, Волхонка, 6, #14

Тел.: +7 095 203-4649

Факс: +7 095 956-8268

info@intsys.dol.ru

http://www.intersystems.ru

Copyright © 1999, InterSystems Corporation. Все права защищены.