##はじめに
「数値計算のための手続き型言語」というイメージが強いfortranだが、fortran2003でオブジェクト指向プログラミングが導入されている。
日本語で簡単なドキュメントがなかったので、とりあえず使ってみる程度のことをまとめてみたいと思う。
##クラスとメソッド
fortranにもclass文があるが、クラスの定義には構造体と同じtype文を用いる。インスタンス変数の定義は構造体と全く同じだ。区切り文字には"."ではなく"%"を用いる。
メソッドの実装はtype文の中にcontains文を使い、その下にtypeの外へのサブルーチンへのポインタをprocedure文で定義する、という形をとる。そして実際の処理は外のサブルーチンで書く。この時サブルーチンの中でそのクラス型の引数を宣言しなければならないが、このときにtype文ではなくclass文を用いる1。
type myclass
character(len=60) :: name
integer :: id
contains
procedure :: set_name => myclass_set_name
end type myclass
!...
subroutine myclass_set_name(self,str)
class(myclass) self
character(len=60) str
!...
end subroutine myclass_set_name
##コンストラクタ
メソッドの中でも、コンストラクタは少しややこしい。
具体的には、オーバーロードというものを用いる。interface文でクラスの別名のようなものを定義しておき、その別名でクラスを返す関数を定義することで、インスタンスの生成のような機能を実装することができる。
一般の言語ではコンストラクタも他のメンバ関数と同じような定義をするが、fortranはコンストラクタのみselfを引数にとらないことに注意。
interface myclass
module procedure init_myclass
end interface myclass
!...
contains
type(myclass) function init_myclass()
!...
end function init_myclass
##サンプルコード
ここでは例として、
- nameという変数
- set_nameというnameを変更するメソッド
を持つクラス「idol」を定義し、実際にメソッドを使うところまで実装したコードを示す。
module mod_class
implicit none
!---------------------------------------------------
! クラス idolの宣言部
type idol
private !とりあえず隠蔽しておく
character(len=60) :: name = "noname"
contains
procedure :: set_name => idol_set_name
procedure :: return_name => idol_return_name
end type idol
!コンストラクタの宣言
interface idol
module procedure init_idol
end interface idol
contains
!---------------------------------------------------
! idolの実装部
! コンストラクタ
type(idol) function init_idol()
write(6,*) "idol instance is generated."
end function init_idol
! コンストラクタ以外のメソッド
subroutine idol_set_name(self,new_name)
class(idol) self
character(len=*) new_name
!メソッドならprivateでもアクセスできる
self%name = new_name
end subroutine idol_set_name
character(len=60) function idol_return_name(self)
class(idol) self
idol_return_name = self%name
end function idol_return_name
end module mod_class
program main
use mod_class
implicit none
type(idol) my_fav_idol
my_fav_idol = idol()
!メソッドを使ってみる
call my_fav_idol%set_name("Momoka")
write(6,*) my_fav_idol%return_name()
end program main
コードの見栄えはよろしくないですが、カプセル化されたライブラリができました。
#注意点
-
インスタンス変数に配列を使った場合、コンストラクタでallocateすることはできないようです。init_idolときちんと書いてやるとallocateできます。なぜでしょう???
なぜかはよくわかりませんができました。
続編→https://qiita.com/Bluepost59/items/8d4b7d7713676fe06472
##参考にしたサイト
http://fortranwiki.org/fortran/show/Object-oriented+programming
https://gist.github.com/YukiYamashina/11366391
-
変数の名前は自分はpython上がりなのでselfとしているが、別にthisでもなんでも構わない。 ↩