Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
20
Help us understand the problem. What is going on with this article?
@bluepost59

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

More than 1 year has passed since last update.

はじめに

「数値計算のための手続き型言語」というイメージが強い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でもなんでも構わない。 

20
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
bluepost59
pythonとかfortranとかC++とか

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
20
Help us understand the problem. What is going on with this article?