Лекция 8 МОДУЛИ Если много параметров ? program prog ... call sub1(X,Y,Z,X1,...,PAR) ... call sub2(X,Y,Z,X1,...,PAR) ... end subroutine sub1(A,B,C,D,...,ZW) ! код подпрограммы end subroutine sub1 subroutine sub2(A,B,C,D,...,ZW) ! код подпрограммы end subroutine sub2 дублируем параметры Если много типов ? program prog type T0 integer x,y,z complex cmpl end type T0 type T1 real x character symb type (T0) style end type T1 call sub3(massiv) ... end subroutine sub3(massiv) ! дублируем ! типы данных T0, T1 end subroutine sub3 subroutine sub4(massiv) ! дублируем ! типы данных T0, T1 end subroutine sub4 Если много процедур ? program prog subroutine sub3(...) interface ! дублируем subroutine ! интерфейсы sub1(...) call sub1(...) ... end subroutine sub3 end subroutine sub1 end interface subroutine sub4(...) ! дублируем interface ! интерфейсы subroutine call sub1(...) sub2(...) end subroutine sub4 ... end subroutine sub2 end interface end Данные и процедуры вместе program sub5 sub1 module типы, данные процедуры sub4 sub2 sub3 Назначение модулей Данные и процедуры в одной программной единице. Обмен данными между процедурами и головной программой. Сокрытие типов, данных и процедур, используемых для промежуточных вычислений. Раздельное написание программ. Состав модуля module имя_модуля use другие модули public private protected описание констант, типов, модульных переменных contains модульные процедуры end module MOD - файлы После компиляции для каждого модуля создается файл имя_модуля.mod на который можно сослаться из других программ. module FLOW ... end module FLOW flow.mod module GRID ... end module GRID grid.mod Additional Include Directories Оператор use Позволяет использовать типы, данные и процедуры модуля program prog use mathlib ! используем модуль mathlib Атрибут only позволяет использовать только "избранные" данные или процедуры. program prog use mathlib, only : dot ! кроме dot, ! все остальные не используются Оператор use Во избежание конфликта одинаковых имен модуля и программной единицы используем операцию =>. module math integer :: A = 1000,B,C end module program prog use math, AM => A integer A A = 80 write(*,*) AM, A end ! 1000 80 Public, private и protected Организация доступа к элементам модуля. Public – данные и процедуры доступны в других программных единицах (по умолчанию). Private – данные и процедуры доступны внутри модуля. Protected – доступны только значения данных в других программных единицах (нельзя изменять данные). Public, private и protected module math integer, public :: A integer, private :: B integer, protected :: C contains subroutine init() A = 1000; B = 2000; C = 3000 end subroutine init end module math program prog use math implicit none call init() A = 50 ! public-переменная, полный доступ B = 100 ! private-переменная, доступна в модуле write(*,*) C ! protected-переменная, доступ к значению С = С+1 ! нельзя изменять значение end Public, private и protected Рекомендации по организации доступа. Public – объявление констант, глобальных переменных, типов и процедур. Все промежуточные и служебные переменные, процедуры и типы следует объявлять как private. Доступ в головной программе к private данным производить при помощи public – процедур. При необходимости использовать значения private-данных применяем protected. Перегрузка процедур Объединение под одним именем множества разных процедур. Процедура вызывается с разным количеством параметров. В вызове процедуры используются параметры разных типов данных. interface общее_имя module procedure имя_1, имя_2 ,..., имя_N end interface Следим за однозначностью выбора одной из объединённых процедур ! Пример перегрузки module math interface prod module procedure umn, scalar, vector end interface contains real function umn(A,B) ! умножение чисел real A,B umn = A*B end function umn real function scalar(A,B) ! скалярное умножение real A(3), B(3) scalar = A(1)*B(1)+A(2)*B(2)+A(3)*B(3) end function scalar subroutine vector(A,B,C) ! векторное умножение real A(3), B(3), C(3) C(1) = A(2)*B(3)-B(2)*A(3) C(2) = A(3)*B(1)-A(1)*B(3) C(3) = A(1)*B(2)-A(2)*B(1) end subroutine vector end module math Пример перегрузки program prog use math real A(3), B(3), C(3) A = [2.0, -4.0, 5.0] B = [4.0, -3.0, 0.0] write(*,*) "Number = ", prod(4.0,5.0) write(*,*) "Scalar product = ", prod(A,B) call prod(A,B,C) write(*,*) "Vector product = ", C end Результат работы программы. Number = 20.00000 Scalar product = 20.00000 Vector product = 15.00000 20.00000 10.00000 Требования для перегрузки В каждой паре перегружаемых процедур хотя бы один параметр должен отвечать двум требованиям: по своему положению не имеет аналогов по типу; module MD interface func module procedure F1, F2 end interface contains real function F1(A,B) ! A real A, B ... end function F1 real function F2(C,D) ! С real C, D ... end function F2 end module MD и B вещественного типа и D вещественного типа Требования для перегрузки формальный параметр с таким же именем отсутствует в списке параметров другой процедуры. module MD ! --- warning interface func module procedure F1, F2 end interface contains real function F1(A,B) real A integer B ... end function F1 real function F2(B,A) real A integer B ... end function F2 end module MD module MD interface func module procedure F1, F2 end interface contains real function F1(A,B) real A integer B ... end function F1 real function F2(C,D) real D integer C ... end function F2 end module MD О модулях … Легкое составление, отладка и модификация программных единиц независимо друг от друга. Использующая программа не знает как устроен модуль, она умеет с ним общаться при помощи процедур. Хороший модуль снаружи лучше чем внутри и его лучше использовать чем построить. Следует избегать создания модулей, работа которых будет зависеть от предыстории.