Функция getOwner ()
Новые классы в языке Java могут быть определены двумя различными способами. Первый — это независимое определение, когда при определении одних классов в их теле могут использоваться только экземпляры других классов.
В AnyLogic новые классы активных объектов определяются с помощью визуальных средств и включений фрагментов программного кода именно так:в проекте объявляется новый класс активного объекта, в данный класс добавляются свои переменные, методы и т. п. Именно это представдено на рис. 7.12, где классы Model, world, Memory и Agent определяются независимо. Экземпляры так определенных активных объектов могут быть включены в любые другие классы активных объектов (конечно, с соблюдением правил иерархии: построенная структура экземпляров активных
объектов должна быть деревом), поскольку все независимо определенные классы "видят" друг друга.
ПуСТЬ НеобХОДИМО ПОЛУЧИТЬ ДОСТУП ИЗ ЛЮбоГО Объекта agent Класса Agere
к переменной х того класса Model, который впоследствии включит данный объект. Для этого в классе Agent нужно получить указатель на объект, кото-рый будет включать объект agent. Если такой указатель m получен, появляется возможность доступа из объекта agent к любому объекту (например, к переменной х) во включающем его классе (как m.х).
В классе Agent выполним следующее:
1. Объявим в классе Agent новую переменную (назовем ее m) типа Model и
инициализируем ее так, чтобы она указывала на "владельца" объекта:
Model m = (Model)getOwner();
2. Для установки значения переменной х класса Model обратимся к ней так
m.х = 1;
Функция getOwner дает в результате владельца данного объекта, но тип ре-зультата нужно явно привести к типу класса-владельца, для чего используется явная конверсия типов. В нашем примере это класс Model. После этого мы получаем возможность обратиться к любому объекту в классе Model.
Рассмотрим другой пример. Пусть определен класс Agent, набор экземпляров которого (реплицированный объект) с именем agent будет впоследствии включен в класс Model. В классе Agent можно выполнить следующие операции, которые будут выполняться в каждом экземпляре этого класса, включенном в класс Model:
□ определить указатель на включающий объект:
Model m = (Model)getOwner();
□ определить число экземпляров в массиве agent: int N = m.agent.size();
□ послать событие "go" стейтчарту агента с номером 0:
m.agent.item(0).statechart.fireEvent("go")
□ определить номер данного экземпляра в наборе agent:
int I=getlndex();
7.7.3. Ключевое слово this
Новый класс можно также определить внутри другого класса. Такое определение называется вложенным. В AnyLogic новые классы некоторых объектов, таких, как таймер, стейтчарт, анимация и т. п., определяются именно так. Для того чтобы из объектов этих типов обратиться к переменным или пара-метрам класса, их включающего, используется ключевое слово this. Это
слово применяется всегда, когда у метода возникает необходимость обра-титься к объекту, который его вызвал. Можно считать, что любой класс содержит переменную с именем this, имеющую тип того объекта, в котором она находится, и указывающую на данный объект. Поэтому, например, если из стейтчарта life, являющегося объектом класса Agent, необходимо обратиться к включающему этот стейтчарт объекту, то нужно записать Agent.this. Если в стейтчарте использовать просто слово this, то мы получим обраще-ние к самому стейтчарту.
Приведем пример использования этого ключевого слова. Пусть, например, при наступлении некоторого события необходимо удалить данного агента, например, если закончилось определенное для него время жизни. Для этого нужно во включающем классе вызвать функцию:
dispose_agent(Agent.this);
Это приведет к удалению экземпляра класса Agent, в котором эта функция вызвана.
Примеры
Приведем примеры решения некоторых проблем доступа для структуры объектов модели, представленной на рис. 7.12.
Обращение к переменным и параметрам объекта из включающего класса:
х = agent.item(O).age;
Этот код, записанный в классе Model, при выполнении модели вызовет при-своение переменной х объекта root значения переменной age экземпляра реплицированного объекта класса Agent, включенного с номером 0 в объект
root.
agent.item(O).age = 0;
agent.item(O).setModified();
Этот код, также записанный в классе Model, не только изменяет значение
переменной age в объекте agent. item(0), но также вызывает и пересчет всех
условий (например, условия срабатывания перехода в стейтчарте), которые
зависят в этом объекте от переменной age и могут влиять на его будущее
поведение.
agent.item(O).set_param(25);
Этот код, записанный в классе Model, при выполнении модели вызовет присвоение параметру param объекта agent.item(O) значения 25, после чего будет вызвана функция onChange_Param, этого объекта. Эта функция может быть определена разработчиком в классе Agent, для возможного изменения состояния экземпляров данного класса при изменении параметра param. Если такая функция разработчиком не определена, по умолчанию выполнится подобная функция с пустым телом.
Доступ к объектам включающего класса:
Model m = (Model)getOwnerf); m.x++; ((m.agent).random()).age = 35;
Пусть эти операторы определены в классе Agent. Первый оператор объявля-ет переменную m типа Model, значение которой устанавливается как объект типа Model, включающий данный объект. Второй оператор увеличивает на 1 переменную х во включающем объекте, т. е. в объекте root. Третий оператор случайно выбирает одного из агентов, включенных в класс Model (т. е. находящихся в объекте root), и переменную age этого объекта устанавливает-в 35. Поскольку операция "точка" левоассоциативна, то есть a.b.c.d понимается как ((а.b).с).d, то третий оператор можно записать без скобок:
m.agent.random().age = 35;
Уничтожение элемента реплицированного набора объектов с именем agent.
dispose_agent(<удаляемый элемент массива agent > )
Заключение
Приведенные здесь сведения по языку Java являются, конечно, недостаточными, чтобы читатель овладел существенной частью его возможностей. Однако использование даже некоторых средств языка позволяет качественно увеличить возможности построения моделей на AnyLogic. Примеры таких моделей мы рассмотрим в следующей главе.
Глава 8