Новые книги

Эта книга — о влиянии информационных технологий на социальную эволюцию. В ней показано, как современные компьютеры и Интернет делают возможным переход к новой общественной формации, в основе которой будут лежать взаимная прозрачность, репутация и децентрализованные методы принятия решений. В книге рассмотрены проблемы, вызванные искажениями и ограничениями распространения информации в современном мире. Предложены способы решения этих проблем с помощью распределённых компьютерных систем. Приведены примеры того, как развитие технологий уменьшает асимметричность информации и влияет на общественные институты, экономику и культуру.
Колонки и статьи Алексея Федорчука, печатавшиеся в журнале LinuxFormat на протяжении 2006-2013 годов, собранные в хронологическом порядке. Они посвящёны UNIX, Linux и другим UNIX-подобным системам, их приложениям, а также идеологическим вопросам Свободного и Открытого Программного Обеспечения (FOSS). Публикуются в авторской редакции.

Объектно-ориентированное программирование на Фортране

5.5.7. Объектно-ориентированное программирование на Фортране

Объектно-ориентированное программирование на Фортране связано с большими техническими трудностями в связи с отсутствием в этом языке структур (записей) и динамических объектов. Но поскольку все еще имеется много любителей Фортрана, следует хотя бы кратко рассмотреть основные принципы реализации на Фортране проекта, разработанного по объектно-ориентированной методологии.

Реализация классов с помощью массивов языка Фортран. В Фортране определен всего один структурный тип данных - массив, так что структуры (записи) тоже следует моделировать. Класс представляется как неявный набор массивов, по одному для каждого атрибута класса. Массивы должны иметь одинаковый размер, который должен быть достаточным для включения всех объектов этого класса, которые будут существовать во время выполнения программы, так как Фортран не поддерживает динамического распределения памяти. Значения индекса массивов представляют уникальный идентификатор объекта внутри соответствующего класса. При этом идентификаторы объектов разных классов будут иметь одинаковые значения, так что программист должен сам следить за тем, какому классу принадлежит объект (впрочем реализация механизма наследования, описываемая ниже, может несколько облегчить это). Все массивы одного и того же класса можно объединить в общий блок. Например, память для тысячи окон из рассматриваемого в этом разделе примера может быть организована следующим образом:

	COMMON/WINDOW/XMIN,YMIN,XMAX,YMAX,WINDOW
	REAL XMIN(1000),YMIN(1000),XMAX(1000),YMAX(1000),WINDOW(1000)
	INTEGER NWINDOW

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

В Фортране нет средств определения новых типов данных, поэтому нет возможности определить тип Length: данные этого типа должны иметь один из определенных в Фортране типов (INTEGER, REAL, COMPLEX, LOGICAL и CHARACTER).

В Стандарте Фортрана ограничена длина идентификаторов, однако большая часть компиляторов поддерживают идентификаторы в 32 и более символов. В примерах фрапгментов фортранных программ предполагается, что допустимы достаточно длинные идентификаторы, которые могут содержать символ подчеркивания ("_"). Если компилятор не поддерживает длинных имен, все идентификаторы из примеров следует заменить более короткими, что, естественно, ухудшит читаемость программ.

Таким образом, в объектной программе на Фортране каждый объект некоторого класса может быть представлен индексом атрибутных массивов этого класса, причем указанный индекс определяет доступ к атрибутам этого объекта:

	INTEGER AWINDOW
	REAL X1
	X1 = XMIN(AWINDOW)

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

	SOUBROUTINE WINDOW__ADD_TO_SELECTIONS (SELF, SHAPE)
	INTEGER SELF, SHAPE

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

	FUNCTION CIRCLE__PICK(X0, Y0, RADIUS, X, Y)
	LOGICAL CIRCLE__PICK
	REAL X0, Y0, RADIUS, X, Y

Размещение объектов в памяти. Обычно размещение новых объектов производится в заранее определенные массивы. Если требуется динамическое распределение памяти, необходимо самому смоделировать управление кучей в своей программе:

	FUNCTION CREATE_WINDOW(X1, Y1, WIDTH, HEIGHT)
	COMMON/WINDOW/XMIN,YMIN,XMAX,YMAX,WINDOW
	REAL XMIN(1000),YMIN(1000),XMAX(1000),YMAX(1000),WINDOW(1000)
	INTEGER NWINDOW
	INTEGER CREATE_WINDOW
	REAL X1, Y1, X2, Y2
	NWINDOW = NWINDOW + 1
	XMIN(NWINDOW) = X1
	YMIN(NWINDOW) = Y1
	XMAX NWINDOW) = X1 + WIDTH
	YMAX NWINDOW) = Y1 + HEIGHT
	CREATE_WINDOW = NWINDOW
	RETURN
	END

Реализация наследования. В Фортране нет записей (структур) и тем более вариантных записей. Поэтому наследование при программировании на Фортране можно реализовать либо в виде универсальной записи, либо моделируя вариантные записи.

Первый способ связан с излишними затратами памяти, его следует применять, когда вариантная часть записей сравнительно невелика. При этом подходе организуется универсальная запись, содержащая все атрибуты корневого класса и все атрибуты всех наследующих ему классов. При работе с конкретным классом из рассматриваемой иерархии классов те атрибуты, которые для него не определены, просто игнорируются. Универсальная запись реализуется, как и раньше, через набор массивов одинаковой длины, по одному на каждое поле записи:

	COMMON/SHAPE/XMIN,YMIN,XMAX,YMAX,WINDOW,RADIUS,NSHAPE
	REAL XMIN(1000),YMIN(1000),XMAX(1000),YMAX(1000),WINDOW(1000)
	REAL RADIUS(1000)
	INTEGER NSHAPE

Второй способ более экономен. Он состоит в представлении класса как набора подклассов, каждый из которых реализован как самостоятельный класс со своим набором массивов и индексами объектов. Каждый класс представляется парой целых массивов: один из этих массивов содержит код подкласса, другой - индексы объектов в соответствующем массиве подкласса. В следующем примере определен класс ITEM, который имеет подклассы SHAPE (содержит не более 1000 объектов) и GROUP (содержит не более 100 объектов). Общий блок CLASSES определяет целочисленный код для каждого класса.

	COMMON/ITEM/ITEM_CLASS,ITEM_ID,NITEM
	INTEGER ITEM_CLASS(1100),ITEM_ID(1100)
	INTEGER NITEM/0/
	COMMON/CLASSES/GROUP,BOX,CIRCLE
	INTEGER GROUP/1/,BOX/2/,CIRCLE/3/

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

	FUNCTION CREATE_CIRCLE(X0,Y0,RADIUS0)
	COMMON/WINDOW/XMIN,YMIN,XMAX,YMAX,WINDOW
	сюда следует поместить описания общих блоков ITEM, SHAPE и CLASSES
	INTEGER CREATE_CIRCLE
	NSHAPE = NSHAPE + 1
	X(NSHAPE) = X0
	Y(NSHAPE) = Y0
	RADIUS(NSHAPE) = RADIUS0
	NITEM = NITEM + 1
	ITEM_CLASS(NITEM) = CIRCLE
	ITEM_ID(NITEM) = NSHAPE
	CREATE_CIRCLE = NITEM
	RETURN
	END

Резолюция методов. Вызовы методов для объектов, класс которых известен во время компиляции, осуществляются как непосредственные вызовы соответствующих фортранных подпрограмм. Остальные объекты должны содержать номер класса (см. выше общий блок CLASSES). Для каждой операции можно составить управляющую подпрограмму, которой в качестве параметров передаются номер класса и индекс объекта. Управляющая подпрограмма содержит оператор перехода по вычислению, который позволяет вызывать требуемый метод:

	    FUNCTION PICK(CLASS,ID,PX,PY)
	    LOGICAL PICK
	    LOGICAL GROUP_PICK,BOX_PICK,CIRCLE_PICK
	    INTEGER CLASS,ID
	    GOTO(100,200,300) CLASS
	    PICK = .FALSE.
	    RETURN
	100 PICK = GROUP_PICK(ID,PX,PY)
	    RETURN
	200 PICK = BOX_PICK(ID,PX,PY)
	    RETURN
	300 PICK = CIRCLE_PICK(ID,PX,PY)
	    RETURN
	    END

Назад | Содержание | Вперед