1. 導入:なぜ「クラス引数」が重要なのか
数値計算のプログラムを書いていると、「円や四角形など、異なる形状の面積を一つの関数で計算したい」といった場面に遭遇します。もし形状ごとに別々の関数を作ると、管理が大変ですよね。ここで登場するのがクラス引数(多態的引数)です。これを使うことで、共通の性質を持つ複数の型を一つの引数で受け取れるようになり、コードの重複を劇的に減らすことができます。
2. 基礎知識:クラス引数とは?
Fortranにおいて、TYPEで定義された型は固定的なものですが、CLASSを使うと、その型を継承した「派生型」も受け入れ可能になります。これを専門用語で「多態性(ポリモーフィズム)」と呼びます。実行時にオブジェクトが「何者であるか」をプログラムが判断し、それぞれの型に合わせて適切な処理を行う仕組みです。
3. 実装・解決策:基底型と派生型の関係
解決策は、まず「基底型(親)」を定義し、それを継承した「派生型(子)」を作ることです。計算用のサブルーチンには引数の型としてCLASSを指定します。こうすることで、親の型を継承していれば、どのような子オブジェクトでも同じインターフェースで処理できるようになります。
4. サンプルプログラム
以下のコードは、円と長方形の面積を計算する簡単な例です。コピーしてコンパイル(gfortranなど)し、実行してみてください。
module geometry_mod
implicit none
! 基底型:面積を計算するインターフェースを持つ
type, abstract :: shape
contains
procedure(area_interface), deferred :: get_area
end type
abstract interface
function area_interface(this) result(res)
import :: shape
class(shape), intent(in) :: this
real :: res
end function
end interface
! 派生型:円
type, extends(shape) :: circle
real :: radius
contains
procedure :: get_area => circle_area
end type
! 派生型:長方形
type, extends(shape) :: rectangle
real :: width, height
contains
procedure :: get_area => rect_area
end type
contains
function circle_area(this) result(res)
class(circle), intent(in) :: this
res = 3.14 this%radius2
end function
function rect_area(this) result(res)
class(rectangle), intent(in) :: this
res = this%width this%height
end function
! 多態的なサブルーチン:ここがポイント!
! class(shape)とすることで、円も長方形も受け取れる
subroutine print_area(obj)
class(shape), intent(in) :: obj
print , "面積は:", obj%get_area()
end subroutine
end module
program main
use geometry_mod
type(circle) :: my_circle
type(rectangle) :: my_rect
my_circle%radius = 5.0
my_rect%width = 2.0; my_rect%height = 4.0
! 同じ関数で異なる型の面積を計算できる
call print_area(my_circle)
call print_area(my_rect)
end program
5. 応用・注意点:現場でのバグ回避
クラス引数を使う際、注意すべきは「型判定」です。受け取ったオブジェクトが特定の型であるか確認したい場合は、SELECT TYPE構文を使用しましょう。また、多態的引数は通常の引数よりも計算コストが僅かに高くなるため、極めて高い計算速度が求められる内側のループ処理などで多用しすぎないよう注意してください。まずは、プログラムの「構造設計」をすっきりさせる目的で活用するのがベストです。

コメント