【入門編】CLASSキーワードとポリモーフィズムの基礎 – モダンFortran言語仕様と実践実践マスター

Fortranで「動的」に操る:`CLASS`キーワードとポリモーフィズムの真髄

こんにちは。宇宙航空の現場で何十年も数値計算と格闘してきた者です。

C言語やPythonからFortranの世界に飛び込んできた皆さん、ようこそ。Fortranと聞くと「古い言語」というイメージを持つかもしれませんが、今のFortran(Fortran 2003以降)は、オブジェクト指向の概念をしっかりと取り入れた、極めて強力な計算エンジンです。

今日は、その中でも「ポリモーフィズム(多態性)」を実現する`CLASS`キーワードについて、現場の泥臭い知見を交えながらお話ししましょう。

1. なぜ「TYPE」ではなく「CLASS」なのか?

Fortranを書き始めると、まずは`TYPE`を使ってデータ構造を定義しますよね。しかし、`TYPE`で宣言された変数は「箱の大きさが決まった静的なもの」です。

一方で、`CLASS`は「その箱の中身は、継承関係にあるどれかになる可能性がある」という動的な柔軟性を持っています。

例えるなら、`TYPE`が「決まった寸法のアルミケース」だとすれば、`CLASS`は「中身に合わせて形を変えられるマジックハンド付きの箱」です。数値計算において、例えば「流体解析のソルバー」を作るとき、乱流モデルを計算の途中で切り替えたいといった場面で、この能力が輝きます。

2. 実践:継承とポリモーフィズムを書いてみる

まずは、基本的な構造を見てみましょう。ここでは「形状(Shape)」という基底クラスを作り、それを継承した「円(Circle)」を扱います。

module shape_mod
implicit none

! 基底クラス:抽象的な形状
type, abstract :: shape
contains
! 継承先で必ず実装を強制する deferred プロシージャ
procedure(calc_area), deferred :: area
end type

! インターフェースの定義
abstract interface
function calc_area(self) result(res)
import :: shape
class(shape), intent(in) :: self
real :: res
end function
end interface

! 継承クラス:円
type, extends(shape) :: circle
real :: radius
contains
procedure :: area => circle_area
end type

contains

function circle_area(self) result(res)
class(circle), intent(in) :: self
res = 3.14159 self%radius2
end function

end module shape_mod

ここがポイント:`CLASS`による動的型付け

`class(shape) :: obj` と宣言することで、この`obj`には`shape`を継承したあらゆる派生型を代入できるようになります。これにより、計算のメインループで「これが円なのか、四角なのか」をいちいち判定せずに、ただ`obj%area()`を呼ぶだけで、中身に応じた計算が自動的に実行されるのです。これがポリモーフィズムの恩恵です。

3. 現場エンジニアからの警告:パフォーマンスへの影響

さて、ここからが「元特任最高数値計算アーキテクト」としての本音です。

`CLASS`は便利ですが、「多用は厳禁」です。なぜなら、`CLASS`経由のメソッド呼び出しは、内部的に「仮想関数テーブル(vtable)」を参照するオーバーヘッドが生じるからです。

  • 密なループ内での使用は避ける: 何億回と回るループの中で`CLASS`メソッドを呼ぶと、コンパイラの最適化(インライン展開など)が阻害され、計算速度がガタ落ちします。
  • 静的な`TYPE`を優先する: 計算の核心部、特に配列計算がボトルネックになる場所では、あえて`CLASS`を使わず、素直に`TYPE`や構造体配列を使うのが、Fortranで速度を出す鉄則です。

最適化のためのヒント

もしどうしても`CLASS`を使う必要があるなら、コンパイル時に以下のようなフラグを検討してください(gfortranの場合):

最適化とポリモーフィズムのバランスを取る設定例
gfortran -O3 -march=native -flto -fno-protect-parens main.f90 -o solver

`-flto`(リンク時最適化)を有効にすることで、`CLASS`越しのメソッド呼び出しでも、コンパイラが賢くインライン展開を試みてくれる可能性が上がります。

最後に:まずは手を動かそう

まずは今日紹介したコードを、手元のコンパイラでビルドしてみてください。最初は違和感があるかもしれませんが、この仕組みを使いこなせると、Fortranコードの保守性が劇的に向上します。

「動的な柔軟性」と「計算速度の硬直性」。この二つのバランスをどう取るかが、一人前のFortranエンジニアへの第一歩です。

何か分からないことがあれば、いつでも聞いてくださいね。皆さんのコードが、計算機上で美しく、かつ爆速で動くことを応援しています!

コメント

タイトルとURLをコピーしました