プログラムを整理し、再利用性を高める強力な機能!
これまでのステップで、サブルーチンや関数を使って処理を部品化する方法を学びました。しかし、プログラムが大規模になってくると、関連する変数、定数、サブルーチン、関数などをまとめて管理したくなりますよね?🤔 そんなときに役立つのがモジュール (MODULE) です!
モジュールは、関連するデータや手続き(サブルーチン、関数)を一つの単位としてまとめるための仕組みです。これにより、プログラムの構造が明確になり、コードの再利用性や保守性が格段に向上します。✨
モジュールの基本的な使い方
モジュールは MODULE
文で始まり、END MODULE
文で終わります。その間に、モジュールに含めたい変数、定数、サブルーチン、関数などを定義します。
モジュールの定義例
MODULE my_constants_module
IMPLICIT NONE
! モジュール内で使用する変数の宣言はここで行う
REAL, PARAMETER :: PI = 3.14159265359 ! 円周率 π
REAL, PARAMETER :: GRAVITY = 9.80665 ! 重力加速度 (m/s^2)
END MODULE my_constants_module
MODULE basic_math_module
IMPLICIT NONE
! このモジュールが依存する他のモジュールを指定できる
! USE my_constants_module ! 必要であれば
CONTAINS ! モジュール内の手続き(サブルーチン、関数)は CONTAINS 以降に書く
FUNCTION circle_area(radius) RESULT(area)
REAL, INTENT(IN) :: radius
REAL :: area
! USE 文でインポートしたモジュールの定数を使える
! もし USE 文がなければ、 my_constants_module::PI のように指定する
REAL, PARAMETER :: PI_local = 3.14159265359 ! またはローカルで定義
area = PI_local * radius**2
END FUNCTION circle_area
SUBROUTINE print_hello()
PRINT *, "Hello from the module!"
END SUBROUTINE print_hello
END MODULE basic_math_module
モジュールの利用方法 (USE文)
定義したモジュールを利用するには、プログラム本体や他のサブルーチン、関数、あるいは別のモジュールの中で USE
文を使います。USE
文は、通常、プログラム単位の先頭(PROGRAM
文やSUBROUTINE
文などの直後、IMPLICIT NONE
よりも後が一般的)に記述します。
PROGRAM main_program
! 利用したいモジュールを USE 文で指定
USE my_constants_module
USE basic_math_module
IMPLICIT NONE
REAL :: r, a
! モジュールで定義された定数を利用
PRINT *, "円周率 Pi =", PI
PRINT *, "重力加速度 g =", GRAVITY
! モジュールで定義された関数を利用
r = 5.0
a = circle_area(r)
PRINT *, "半径", r, "の円の面積:", a
! モジュールで定義されたサブルーチンを利用
CALL print_hello()
END PROGRAM main_program
モジュールの利点 💪
モジュールを使うことには、たくさんのメリットがあります。
- コードの再利用性向上: 共通して使う定数や関数などをモジュールにまとめておけば、複数のプログラムやサブルーチンから簡単に呼び出して使えます。同じコードを何度も書く必要がなくなります。
- プログラムの構造化: 関連する機能をモジュール単位に分割することで、プログラム全体の構造が分かりやすくなります。大規模なプログラムの開発や保守が容易になります。
- 名前空間の分離: モジュールは独立した名前空間を提供します。これにより、モジュール内で定義した変数名や手続き名が、プログラムの他の部分や別のモジュールで定義された名前と衝突するのを防ぐことができます。
- インターフェースの明確化: モジュール内の要素(変数、手続きなど)を外部に公開するかどうかを制御できます(後述の
PUBLIC
/PRIVATE
属性)。これにより、モジュールの使い方を明確にし、意図しない使われ方を防ぐことができます。 - グローバル変数の代替: 複数のサブルーチンや関数で共通して使いたい変数をモジュール変数として定義することで、グローバル変数のように利用できます。ただし、グローバル変数の多用はプログラムを複雑にする可能性があるため、注意が必要です。モジュールを使うことで、どの変数がどこで使われているか追跡しやすくなります。
PUBLIC属性とPRIVATE属性によるアクセス制御
モジュール内の要素(変数、定数、サブルーチン、関数など)が、モジュールを USE
した外部のプログラム単位からアクセスできるかどうかを制御するために、PUBLIC
属性と PRIVATE
属性を使用します。
- PUBLIC属性: モジュール外部からアクセス可能です。これはデフォルトの属性なので、明示的に指定しない限り
PUBLIC
になります。 - PRIVATE属性: モジュール内部からのみアクセス可能です。モジュール外部からはアクセスできません。
これらの属性は、個々の変数や手続きに対して指定することも、モジュール全体に対してデフォルトのアクセスレベルを設定し、一部の要素だけ逆の属性を指定することも可能です。
MODULE access_control_module
IMPLICIT NONE
! デフォルトを PRIVATE に設定 (モジュール内のほとんどを隠蔽したい場合)
PRIVATE
! PUBLIC 属性を明示的に指定したものだけが外部からアクセス可能になる
PUBLIC :: shared_variable, useful_function
INTEGER :: shared_variable = 100 ! これは外部からアクセス可能
REAL :: internal_helper_variable = 0.5 ! これは外部からアクセス不可
CONTAINS
FUNCTION useful_function(x) RESULT(y) ! これは外部からアクセス可能
REAL, INTENT(IN) :: x
REAL :: y
y = x * internal_helper_variable ! 内部変数は使える
CALL internal_subroutine() ! 内部サブルーチンも呼べる
END FUNCTION useful_function
SUBROUTINE internal_subroutine() ! これは外部からアクセス不可
PRINT *, "This is an internal subroutine."
PRINT *, "Internal helper variable:", internal_helper_variable
END SUBROUTINE internal_subroutine
END MODULE access_control_module
PROGRAM main_access_test
USE access_control_module
IMPLICIT NONE
REAL :: result
! PUBLIC な変数や関数はアクセスできる
PRINT *, "Shared variable:", shared_variable
result = useful_function(5.0)
PRINT *, "Result from useful function:", result
! PRIVATE な変数やサブルーチンはアクセスできない (コンパイルエラーになる)
! PRINT *, internal_helper_variable
! CALL internal_subroutine()
END PROGRAM main_access_test
モジュールのコンパイル ⚙️
モジュールを使用するプログラムをコンパイルする場合、通常はモジュールを定義しているソースファイルを先にコンパイルする必要があります。コンパイラはモジュールをコンパイルする際に、モジュールの情報を含んだ特別なファイル(gfortran の場合は .mod
ファイル)を生成します。そして、そのモジュールを USE
しているプログラムをコンパイルする際に、この .mod
ファイルを参照します。
例えば、my_modules.f90
というファイルにモジュールが定義されていて、main_program.f90
というファイルがそれを利用している場合、gfortran を使うと以下のようにコンパイルします。
# 1. モジュールを定義しているファイルを先にコンパイル
gfortran -c my_modules.f90
# これにより my_constants_module.mod や basic_math_module.mod といったファイルが生成される
# 2. モジュールを利用するプログラム本体をコンパイル
gfortran -c main_program.f90
# 3. オブジェクトファイルをリンクして実行可能ファイルを作成
gfortran my_modules.o main_program.o -o my_executable
# または、まとめてコンパイル (コンパイラが依存関係を解決してくれる場合がある)
# ただし、ファイル名の順序が重要になることがある
gfortran my_modules.f90 main_program.f90 -o my_executable
まとめ
モジュールは Fortran プログラミングにおいて非常に重要で強力な機能です。関連するデータや手続きをまとめ、コードの再利用性、可読性、保守性を大幅に向上させることができます。特に、チームで開発を行う場合や、大規模なプログラムを作成する場合には必須のテクニックと言えるでしょう。😊
最初は少し難しく感じるかもしれませんが、積極的にモジュールを活用して、整理された効率的な Fortran プログラムを作成するスキルを身につけていきましょう!💪
参考情報
-
Fortran Wiki (Modules): Fortranのモジュールに関する基本的な情報(英語)
https://fortran-lang.org/learn/best_practices/modules -
gfortran ドキュメント (Modules): GNU Fortran コンパイラにおけるモジュールの扱いに関するドキュメント(英語)
https://gcc.gnu.org/onlinedocs/gfortran/Modules.html
上記の情報は一般的な解説であり、特定のコンパイラや環境によっては挙動が異なる場合があります。詳細については、お使いのコンパイラのマニュアル等をご参照ください。
コメント