Edited at

fortranでもオブジェクト指向したい!


はじめに

「数値計算のための手続き型言語」というイメージが強いfortranだが、fortran2003でオブジェクト指向プログラミングが導入されている。

日本語で簡単なドキュメントがなかったので、とりあえず使ってみる程度のことをまとめてみたいと思う。


クラスとメソッド

fortranにもclass文があるが、クラスの定義には構造体と同じtype文を用いる。インスタンス変数の定義は構造体と全く同じだ。区切り文字には"."ではなく"%"を用いる。

メソッドの実装はtype文の中にcontains文を使い、その下にtypeの外へのサブルーチンへのポインタをprocedure文で定義する、という形をとる。そして実際の処理は外のサブルーチンで書く。この時サブルーチンの中でそのクラス型の引数を宣言しなければならないが、このときにtype文ではなくclass文を用いる1


mod_myclass.f90

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を引数にとらないことに注意。


mod_myclass.f90

   interface myclass

module procedure init_myclass
end interface myclass
!...
contains
type(myclass) function init_myclass()
!...
end function init_myclass


サンプルコード

ここでは例として、


  • nameという変数

  • set_nameというnameを変更するメソッド

を持つクラス「idol」を定義し、実際にメソッドを使うところまで実装したコードを示す。


mod_class.f90

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



sample.f90

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





  1. 変数の名前は自分はpython上がりなのでselfとしているが、別にthisでもなんでも構わない。