Типы данных и пакеты

 

Для моделирования непрерывных систем необходим минимальный набор типов данных: скалярный вещественный тип, типы «вектор» и «матрица», а также целые числа для вычисления индексов векторов и матриц. Пакет Simulink, например, обходится вообще без скалярных вещественных переменных, используя вместо них матрицу размерности 1 ´ 1.

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

Для систем со сложной структурой желательно наличие типа «запись» для передачи в компактной форме наборов взаимосвязанных данных между блоками. Для непрерывных моделей, где данные передаются в виде векторов, гораздо удобнее передавать набор {x,y,z,Vx,Vy,Vz}, чем вектор размерности шесть и помнить, что скорость по оси z - это 5-й элемент вектора.

Для моделирования систем со сложными алгоритмами желательно использование алгоритмических (программных) объектов и массивов объектов. Для систем с динамической и регулярной структурой необходимы переменные типа «блок» и массивы блоков. В моделировании актуально использование ограниченных типов (например, type Voltage = Real 0. .240;) и типов с указанием единиц измерения. В UML «тип» трактуется просто как особый класс в Java. В языке Modelica тип считается особым видом класса и используется отношение наследования между типами для ограничения области значений или добавления новых компонентов в записи.

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

Для объединения элементов описания в группы ООП предлагает механизм пакетов. Пакет (package) ‑ это контейнер для группы компонентов, ограничивающий область их видимости. Компоненты, объявленные как public, видимы извне под составным именем, включающим в качестве префикса имя пакета, например, Blocks, CGain, где Blocks имя библиотеки стандартных блоков. «Библиотека» в ООМ является практически синонимом термина «пакет». Остальные компоненты видимы только внутри данного пакета. UML рекомендует по умолчанию объявлять компоненты как public. Конкретная модель рассматривается как некоторый анонимный пакет.

В отличие от языков программирования, где компонентами пакета являются только классы, естественными компонентами пакета в ООМ являются также константы и алгоритмические функции. Если язык моделирования включает в себя алгоритмические объекты, т.е. объекты в понимании языков программирования, например, Java-объекты, то в пакете можно объявить класс со статическими конечными (final) переменными и методами. Примером может служить класс Math в пакете java.langi, где, например, имеются статическая переменная PI и статическая функция sin. В противном случае константы и алгоритмические функции придется считать равноправными компонентами пакета.

Для того чтобы в одном пакете был виден другой, его нужно импортировать, т.е. указать явным образом на его использование. Следует учитывать, что отношение импортирования не является транзитивным, т.е. если пакет Р2 импортирует пакет P1, а P3 импортирует Р2, то это вовсе не означает, что P3 импортирует P1. Импортирование пакета означает, что его имя становится видимым в импортирующем пакете или модели. Следует отметить, что импорт собственно пакета в языке Java не требуется, поскольку используется понятие корневой точки CLASSPATH и соглашение о соответствии иерархии пакетов иерархии каталогов файловой системы. Поэтому все пакеты, определенные ниже указанной точки, автоматически становятся видимыми. Если же такого рода соглашения не используются, то импорт пакета нужно явно декларировать.

packagemodel {

import Blocks; //объявление импорта 1

import Blocks.СGain; //объявление импорта 2

import Blocks.*; //объявление импорта 3

import LinearBlocks./; //объявление импорта 4

…..

Blocks.CGain Amp = new Blocks.CGain (K=2); // оператор 1

CGain Amp = new CGain (K=2); // оператор 2

LinearBlocks.CGain Amp2 = new LinearBlocks.CGain (K=100; // оператор 3

……

};

Таким образом, если в пакете или модели импортируется пакет (объявление импорта 1 в примере), то экспортируемые компоненты этого пакета доступны через префикс пакета (оператор 1 в примере). Если импортируется конкретный компонент (объявление импорта 2) или импортируются все компоненты пакета (объявление импорта 3), то компонент доступен по своему имени без префикса пакета (оператор 2). Если в данном пакете или модели определен свой компонент с таким же именем, например блок CGain, то он скрывает импортируемый компонент. Если компонент с одним и тем же именем определен более чем в одном импортируемом пакете, например, блок CGain определен в пакете Blocks (объявление импорта 1) и в пакете LinearBlocks (объявление импорта 4), то возникает конфликт имен и к нужному компоненту придется обращаться через префикс соответствующего пакета (операторы 1 и 4).

В качестве компонента пакета может выступать другой пакет. Например, если пакет Sources вложен в пакет Blocks, то обращаться извне к генератору синусоиды нужно как Blocks.Sources.CSineGenerator. Относительно видимости компонентов пакета во вложенных пакетах имеется два решения:

- в Java и Modelica все компоненты охватывающего пакета видны во вложенном пакете.

- в Java и пакетах Modelica со статусом encapsulated в пакете видимы только собственные и явно импортируемые компоненты.

UML предполагает наследование пакетов, причем, в производном пакете наследуются все компоненты базового, есть возможность добавить новые компоненты и переопределить унаследованные. В пакете, соответствующем текущему проекту, имеется специальный класс с зарезервированным идентификатором (например, Model или TestBench), задающий блок-контейнер, в котором помещена структурная схема моделируемой системы или той ее части, с которой в данный момент проводится вычислительный эксперимент. Экземпляр именно этого класса должна создать исполняющая система пакета моделирования в начале прогона модели.