拡張構造体を使ったプログラミングにおける問題と解決策

提供: ComplexRI: Manual
ナビゲーションに移動 検索に移動

Fortran で拡張構造体を利用する場合、言語仕様に伴ういくつかの困難が存在する。 本ページではそれらについて示すとともに、現状での解決策等を提示する。

同クラス内での代入

問題点:拡張後の構造体に拡張前の構造体を代入することができない。

例:

type aaa
  integer :: bbb
endtype

type,extends(aaa) :: aaa_ex
  integer :: ccc
endtype

とした場合に aaa_ex = aaa がエラーとなる。

解決策:ユーザー定義代入を定義する。

例:

type aaa
  integer :: bbb
endtype

type,extends(aaa) :: aaa_ex
  integer :: ccc
contains
  generic :: assignment(=) => equal
  procedure :: equal
endtype
subroutine equal(out,in)
  implicit none
  class(aaa),intent(inout) :: out
    !!! intent(inout) 指定は必須。
    !!! そうしないと代入時に ccc が未定義となる。
  type(aaa),intent(in) :: in

  out%aaa = in%aaa
  !!! 各成分ごとの代入が必要。
  !!! out = in では subroutine equal の再起呼び出しとなってしまう。
  !!! この解決策はメンバ変数が多い場合に問題となる。

endsubroutine


オーバーロード時の元関数呼び出し

問題点:プロシージャのオーバーロード時に元のプロシージャが呼び出せなくなる。

例:

module aaa_module
  implicit none

  type aaa
  contains
    procedure :: sub
  endtype

...

endmodule

module aaa_ex_module
  use aaa_module,only: aaa
  implicit none

  type,extends(aaa) :: aaa_ex
  contains
    procedure :: sub    !!! オーバーロード
  endtype

contains

  subroutine sub(self)
    implicit none
    class(aaa_ex) :: self

    元の sub を呼べない。

  endsubroutine

endsubroutine 

解決策:オーバーロードする関数を generic とし、元の sub を呼び出す場合は詳細なプロシージャ名を指定する。

例:

module aaa_module
  implicit none

  type aaa
  contains
    generic :: sub => sub_original
    procedure :: sub_original
  endtype

...

endmodule

module aaa_ex_module
  implicit none

  type,extends(aaa) :: aaa_ex
  contains
    generic :: sub => sub_ex   !!! オーバーロード
    procedure :: sub_ex
  endtype

contains

  subroutine sub_ex(self)
    implicit none
    class(aaa_ex) :: self

    call self%sub_original()

    ...

  endsubroutine

endsubroutine