Структуры, более сложные, чем примитивные типы, задаются с помощью классов, согласно объектно-ориентированной методологии. Объяснить детально концепцию объектно-ориентированного проектирования в рамках одного небольшого документа не представляется возможным: этот предмет заслуживает написания отдельной книги, и таких книг уже написано множество. Все, что мы можем сделать здесь — это дать общее понимание того, что такое объектно-ориентированность, и ввести такие фундаментальные понятия, как класс, метод, объект, экземпляр, подкласс, наследование.
Вам не нужно пытаться выучить или полностью понять фрагменты кода в этом разделе. Будет достаточно, если прочитав этот раздел, вы будете просто знать, например, что диаграмма состояний в вашей модели является экземпляром класса AnyLogic Statechart, и вы можете узнать, является ли какое-то ее определенное состояние активным в данный момент с помощью метода statechart.isStateActive().
Давайте рассмотрим пример. Предположим, что вы работаете с локальной картой — оперируете координатами точек на карте и вычисляете расстояния между ними. Вы, конечно, можете запомнить два вещественных значения x и y для каждого местоположения и написать функцию distance(x1, y1, x2, y2), которая будет вычислять расстояния между двумя парами координат. Но куда более элегантным будет создать новую сущность, которая будет объединять вместе координаты и метод, вычисляющий расстояние до другой точки. В объектно-ориентированном программировании такая сущность называется классом. Объявление Java класса для точки местоположения на карте будет выглядеть таким образом:
class Location { // конструктор: создает объект Location с заданными координатами
Location( double xcoord, double ycoord ) {
x = xcoord;
y = ycoord;
} // два поля типа double
double x; // x координата местоположения
double y; // y координата местоположения
// метод (функция): вычисляет расстояние от данного места до другого
double distanceTo( Location other ) {
double dx = other.x - x;
double dy = other.y - y;
return sqrt( dx*dx + dy*dy );
}
}
Задав такой класс, мы можем написать очень простой и читаемый код для работы с картой, например, такой:
Location origin = new Location( 0, 0 ); // создаем первое местоположение
Location destination = new Location( 250, 470 ); // создаем второе
double distance = origin.distanceTo( destination ); // вычисляем расстояние между ними
Точки origin и destination являются объектами и экземплярами класса Location. Выражение new Location( 250, 470 ) является вызовом конструктора, оно создает и возвращает новый экземпляр класса Location с заданными координатами. Выражение origin.distanceTo( destination ) является вызовом метода: просит объект origin вычислить расстояние до другого объекта destination.
Location target; // переменная объявлена без инициализации и равна null
target = warehouse; // переменной target присвоен объект (на который ссылается переменная) warehouse
// теперь target и warehouse указывают на один и тот же объект
…
target = null; // target «забывает» о warehouse и снова равен null
Теперь предположим, что некоторые из этих точек, заданных вами в двумерном пространстве, соответствуют городам. У города есть название и численность населения. Чтобы эффективно управлять городами, мы расширим класс Location, добавив в него еще два поля: name и population. Давайте назовем этот новый класс City. В Java это будет выглядеть следующим образом:
class City extends Location { //объявление класса City, расширяющего класс Location
//конструктор класса City
City( String n, double x, double y ) {
super( x, y ); //вызов конструктора суперкласса с параметрами x и y
name = n; //поле population не инициализируется в конструкторе, это будет сделано впоследствии
} //поля класса City
String name;
int population;
}
City в данном примере является подклассом класса Location, а Location — суперклассом (или базовым классом) для класса City. City наследует все свойства класса Location и добавляет новые. Посмотрите, как элегантно выглядит код, определяющий крупнейший город в радиусе 100 километров от заданной точки point класса Location (мы предполагаем, что существует коллекция cities, в которой хранятся все города):
int pop = 0; //здесь мы будем запоминать самую большую численность населения, найденную к данному моменту
City biggestcity = null; //здесь мы будем запоминать наилучший город, найденный к данному моменту
for( City city : cities ) { //для каждого города в коллекции
citiesif( point.distanceTo( city ) < 100 && city.population > pop ) { // если этот город лучше, чем найденные ранее
biggestcity = city; //запоминаем его
pop = city.population; //и запоминаем численность его населения
}
}
traceln( "Крупнейший город в радиусе 100 км " + city.name ); // распечатываем результат поиска
Обратите внимание, что хотя city является объектом класса City, который «больше», чем Location, при необходимости (например, при вызове метода distanceTo() класса Location) с ним можно по-прежнему работать как с объектом класса Location.
А что, если наоборот? вы можете объявить переменную класса Location и присвоить ей объект класса City (подкласс класса Location):
Location place = laJolla;
С этим проблем не возникнет. Но если вы затем попробуете получить доступ к численности населения (полю population объекта place), то Java выдаст ошибку:
int p = place.population; //error: "population cannot be resolved or is not a field"
Это происходит потому, что Java не знает о том, что place в действительности является объектом класса City. Чтобы устранить такое «непонимание», нужно сделать следующее:
- проверить, является ли объект в действительности объектом какого-то определенного подкласса с помощью оператора instanceof: <объект> instanceof <класс>
- «привести» этот объект от суперкласса к подклассу, написав имя подкласса в скобках перед именем объекта: (<класс>)<объект>
Типичный образец кода:
if( place instanceof City ) {
City city = (City)place;
int p = city.population;
…
}
В сущности все элементы, используемые вами при построении моделей, являются объектами Java классов AnyLogic. Вы можете найти имена Java классов, соответствующие всем этим элементам, в Справочнике классов AnyLogic. Если вы захотите узнать, какие методы предоставляет Java для того или иного типа элемента, вам нужно будет просто найти нужный класс в Справочнике и ознакомиться со списком поддерживаемых этим классом полей и методов.
-
Как мы можем улучшить эту статью?
-