モジュールはFortran90で追加された機能で、変数、定数、手続などをまとめることができる便利な機能です。
モジュールは記述パターンがいくつかあるので、今回はサンプル多めです。
モジュールの記述ルール
モジュールは以下のように定義します。モジュール1はモジュール名、変数1は変数名です。contains以下にモジュール内変数を参照・変更可能なモジュール内副プログラムを定義することができます(モジュール内副プログラムは必須ではありません)。
module モジュール1
__implicit none
__変数の型宣言 :: 変数1
__contains
____モジュール内副プログラムの定義
end module モジュール1
モジュール内変数と副プログラムを外部プログラムから利用する場合には以下のように use 文を用います。use文はプログラムの最初に記述します。
program プログラム1
__use モジュール1
__implicit none
__処理1
end program プログラム1
モジュールに関するコメント
モジュールは便利な機能ですが、use文による変数共有によって、変数がどこで変わったのか、わかり難くなることがあります。プログラムが大規模になってきたときに、この傾向が顕著になります。
この問題を回避する方法のひとつが、モジュール内変数を外部から隠蔽することです。これをカプセル化といいます。
しかしながら、コーディングの手間は増えてしまうため、プログラムの性質(一時利用か長期継続開発か、あるいは、個人開発かチームで開発か、等々)を考慮して、モジュールを設計して下さい。
サンプルプログラム
モジュール内変数の隠蔽レベルの異なるプログラム例を以下に示します。
隠蔽Lv1
まずは、ほとんど隠蔽しない例です。
プログラムの中身は、xとyの和をzに代入して出力しているだけの単純なものです。
以下のFortranプログラムをコピペし、****.f90の名前で保存して下さい(****の部分は適当でいいです)。コピペが面倒な場合は、こちらからダウンロードして下さい(右クリックメニューから保存)。→ sample10_lv1.f90
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | !---------------------------- モジュール module sample10_module implicit none private ! デフォルト設定(非公開) real(8), public, save :: x, y, z ! 変数の型宣言(公開) public :: sample10_module_ini ! 副プログラムの宣言(公開) ! モジュール内副プログラムの定義 contains subroutine sample10_module_ini() implicit none x = 1.0d0 y = 2.0d0 z = 0.0d0 end subroutine sample10_module_ini end module sample10_module !---------------------------- メインプログラム program sample10_main use sample10_module, only: z, & ! 使用変数 & sample10_module_ini ! 使用副プログラム implicit none call sample10_module_ini() ! 初期値設定 call sample10_add() ! 演算 write(*,'(f5.1)') z ! 出力 end program sample10_main !---------------------------- 副プログラム subroutine sample10_add() use sample10_module, only: x, y, z ! 使用変数 implicit none z = x + y end subroutine sample10_add |
使い方は、前記事と同様に、****.f90を以下の****.batにドラッグ&ドロップするだけです。
64bit用 → comp_exe_64.bat
32bit用 → comp_exe_32.bat
プログラムの中身を以下に詳しく解説します。
2-15行目はモジュールの定義です。
4行目はモジュール内変数と副プログラムを公開するかどうかを決める設定です。privateを宣言しているので、デフォルトで非公開設定です。(何も書かない、またはpublicと記述すれば公開となります)
5, 6行目は変数と副プログラムの宣言です。両方とも公開(public)設定としています。
*このサンプルでは、デフォルトはprivate、個々の変数と副プログラムはpublicという、まわりくどい記述をしていますが、後述する変数の隠蔽レベルの高いモジュールの書き方と合わせているだけで、あまり意味はありません。
9-14行目はモジュール内副プログラムの定義です。contains以下では、モジュール内変数(x, y, z)を参照・変更できます。この際、引数は必要ありません。
17-24行目はメインプログラムです。
18, 19行目は、only文によって、使用する変数と副プログラムを指定しています。ここで記載されていない変数(x, y)はメインプログラムから参照・変更できません。
*この例では変数が少ないので、あまり恩恵が感じられませんが、変数が多いモジュールを使用するときは、only文による限定公開設定は、プログラムの保守性向上のために、簡便で有効な手段です。
26-30行目はxとyの和をzに代入する副プログラムです。
隠蔽Lv2
上記サンプルと同じ処理で、変数へのアクセスを少し変えたものが以下のサンプルです。どこが変わったかわかりますか?
副プログラムを二段階にすることで、変数の入出力を、intent(in), intent(out)文を用いて明示しています。ちょっとした修正ですが、変数の変更箇所が上記サンプルに比べて特定し易くなっています。
右クリックメニューから保存→ sample10_lv2.f90
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | !---------------------------- モジュール module sample10_module implicit none private ! デフォルト設定(非公開) real(8), public, save :: x, y, z ! 変数の型宣言(公開) public :: sample10_module_ini ! 副プログラムの宣言(公開) ! モジュール内副プログラムの定義 contains subroutine sample10_module_ini() implicit none x = 1.0d0 y = 2.0d0 z = 0.0d0 end subroutine sample10_module_ini end module sample10_module !---------------------------- メインプログラム program sample10_main use sample10_module, only: z, & ! 使用変数 & sample10_module_ini ! 使用副プログラム implicit none call sample10_module_ini() ! 初期値設定 call sample10_add_master() ! 演算 write(*,'(f5.1)') z ! 出力 end program sample10_main !---------------------------- 副プログラム(主) subroutine sample10_add_master() use sample10_module, only: x, y, z ! 使用変数 implicit none call sample10_add_slave(z,x,y) end subroutine sample10_add_master !---------------------------- 副プログラム(従) subroutine sample10_add_slave(z,x,y) implicit none real(8), intent(in) :: x, y ! 入力変数 real(8), intent(out) :: z ! 出力変数 z = x + y end subroutine sample10_add_slave |
隠蔽Lv3
このサンプルでは、モジュール内変数を非公開としています。5行目の変数宣言にpublicを記載していないので、デフォルト設定のprivateが有効になります。
外部プログラムからモジュール内変数にアクセスするためには、モジュール内副プログラムを介する必要があります。
モジュール内変数は、外部からは参照もできないため、21-24行目に外部参照のための関数を定義しています。
右クリックメニューから保存→ sample10_lv3.f90
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | !---------------------------- モジュール module sample10_module implicit none private ! デフォルト設定(非公開) real(8), save :: x, y, z ! 変数の型宣言(非公開) public :: sample10_module_ini ! 副プログラムの宣言(公開) public :: sample10_module_add public :: sample10_module_get_z ! モジュール内副プログラムの定義 contains subroutine sample10_module_ini() implicit none x = 1.0d0 y = 2.0d0 z = 0.0d0 end subroutine sample10_module_ini subroutine sample10_module_add() implicit none z = x + y end subroutine sample10_module_add real(8) function sample10_module_get_z() implicit none sample10_module_get_z = z end function sample10_module_get_z end module sample10_module !---------------------------- メインプログラム program sample10_main use sample10_module implicit none call sample10_module_ini() ! 初期値設定 call sample10_module_add() ! 演算 write(*,'(f5.1)') sample10_module_get_z() ! 出力 end program sample10_main |
→ 次の記事へ(配列(2)-動的割付け)
← 前の記事へ(副プログラム)
目次(Fortran90)