In C++ you often define a class over two file types: header files, and .cpp files. The header files define variables, and function arguments (e.g. void myfunc(int a, int b);
), while the .cpp files contain the code for what the functions do.
This is nice for when you have big classes with lots of functions. You can see overall structure in the header file, and you can organize functions over many different .cpp files. No single file gets too long and unwieldy.
My question is, what is the best way to emulate this organization in Fortran, distributing the definition of a single derived type over many files? Using a single file can be really unwieldy sometimes.
Here is what I’m currently thinking. Analogous to a class defined in a C++ header, you can define an abstract types in Fortran, with deferred subroutines:
module myobject_abs
implicit none
type, abstract :: mytype_abs
integer :: a
contains
procedure (mytype_printa), deferred :: printa
procedure (mytype_add2a), deferred :: add2a
end type
abstract interface
subroutine mytype_printa(self)
import mytype_abs
class (mytype_abs),intent(in) :: self
end subroutine
subroutine mytype_add2a(self, b)
import mytype_abs
class (mytype_abs),intent(inout) :: self
integer, intent(in) :: b
end subroutine
end interface
end module
Then you define the subroutines in separate modules (or the same module). This is analogous to .cpp files:
module myobject_subs1
use myobject_abs, only: mytype_abs
implicit none
contains
subroutine printa(my)
class(mytype_abs), intent(in) :: my
print*,my%a
end subroutine
end module
module myobject_subs2
use myobject_abs, only: mytype_abs
implicit none
contains
subroutine add2a(my, b)
class(mytype_abs), intent(inout) :: my
integer, intent(in) :: b
my%a = my%a + b
end subroutine
end module
Finally, you knit everything together in a final module
module myobject
use myobject_abs, only: mytype_abs
implicit none
type, extends(mytype_abs) :: mytype
contains
procedure :: printa => mytype_printa
procedure :: add2a => mytype_add2a
end type
contains
subroutine mytype_printa(self)
use myobject_subs1, only: printa
class(mytype), intent(in) :: self
call printa(self)
end subroutine
subroutine mytype_add2a(self, b)
use myobject_subs2, only: add2a
class(mytype), intent(inout) :: self
integer, intent(in) :: b
call add2a(self, b)
end subroutine
end module
Maybe there is a better solution?