next up previous contents
След.: Перегрузка Выше: Объектно-ориентированное программирование Пред.: Конструкция выбора типа   Содержание


Инкапсуляция

Инкапсуляция -- объединение данных и кода, работающего с ними, в один тип данных -- объект. В принципе, процедурные указатели позволяют помещать ссылки на процедуры в производные типы, и это довольно гибкий метод, позволяющий менять при необходимости цели указателя.

Если этого не требуется, можно использовать более простую технологию инкапсуляции -- связанные с типом процедуры. По аналогии с программными единицами объявления процедур, связанных с типом, отделяются от объявления данных словом CONTAINS. Объявляет процедуру оператор PROCEDURE, его вид

PROCEDURE [(интрф)] [[,атриб ]::] имя[=> проц]

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

В число атрибутов входят PUBLIC и PRIVATE с понятным смыслом (по умолчанию процедуры открыты).

Первым аргументом процедуры является объект того же типа, что и тот, с которым процедура связана. Он передается автоматически, то есть процедура вызывается с фактическими аргументами только начиная со второго, а первым идет объект производного типа. Если это нежелательно, следует указать атрибут NOPASS. Атрибут PASS можно указать явно (он назначается по умолчанию), причем можно указать в скобках имя формального параметра.

Атрибут DEFERRED может указываться только если тип абстрактный, и означает, что процедура отложена -- не имеет реализации. Типы-потомки должны определить эту процедуру. Обязательно должен быть указан абстрактный интерфейс (ABSTRACT INTERFACE). Тип объявляется с указанием слова ABSTRACT. Пример [12]:

TYPE, ABSTRACT:: FHANDLE

CONTAINS

PROCEDURE(OPEN_F), DEFERRED, PASS:: OPEN

END TYPE

ABSTRACT INTERFACE

SUBROUTINE OPEN_F(H)

CLASS(FHANDLE),INTENT(INOUT):: H

END SUBROUTINE OPEN_FILE

END INTERFACE

Предполагается, что потомки будут иметь поля, описывающие файл, а процедура будет открывать файл на основе этой информации. Абстрактный тип может быть объявленным типом полиморфного объекта, но нельзя объявлять, размещать и конструировать объекты этого типа.

Если процедура типа-потомка совпадает по имени и аргументам (за исключением первого аргумента, если назначен атрибут PASS) с процедурой предка, то она переопределяет ее. При этом новая не должна быть скрытой, если открыта старая. Доступ к процедуре предка возможен через скрытое поле-предка. Однако можно запретить переопределение процедуры, назначив ей атрибут NON_OVERRIDABLE.

Можно связать с типом завершающие процедуры, объявив их с помощью слова FINAL вместо PROCEDURE. Процедуры должны иметь один параметр производного типа-хозяина, причем он не должен быть исходящим. Его конфигурация и параметры длины должны, если есть, быть перенимаемыми. Фактическим аргументом будет объект, существование которого завершается. Предназначение завершающих процедур -- освободить размещенные объекты и т.п. Тип завершаемый, если у него есть хотя бы одна завершающая процедура или завершаемое поле, которое не указатель и не размещаемое. Объект, который не указатель, завершаем тогда, когда его тип завершаем. Когда завершаемый объект прекращает существование, вызывается подходящая по параметрам типа и рангу завершающая процедура; если таковой нет, вызывается поэлементная с подходящими параметрами типа. Затем завершаются все завершаемые поля. Если они массивны, каждый элемент завершается отдельным вызовом. Такой алгоритм означает, что завершающая процедура должна работать только с полями, которые сами не являются завершаемыми: их завершающие процедуры будут вызваны после. В Стандарте [14] есть пример (приложение C.1.7) параметризованного производного типа с тремя завершающими подпрограммами: одна завершает скаляр, другая -- одномерный массив, а третья -- поэлементна, причем различаются они и параметром типа.

Завершающие процедуры являются деструкторами в терминологии ООП. Конструкторов, вызываемых автоматически при создании объекта, в Фортране нет. Однако их можно создавать, пользуясь описанным в Стандарте способом -- объединяя одну или несколько функций производного типа, связанных с этим типом, под родовым именем, совпадающим с именем типа. См. стр. [*], где приведен пример.



Ilya A. Chernov 2012-12-19
X