Given the minimal working example below, I would like to modify it to avoid copy/pasting the calls of
call func_some_calc1(par)
call func_some_calc2(par)
in both main_func_problem1
and main_func_problem2
.
Ideally I want to have one function main_func
that is behaving differently for input parameters of type t_parameters_problem1
and t_parameters_problem2
. I could declare its par
parameter of base type class(t_parameters_base)
, but then having a switch inside that function depending on the actual argument type (using select type
) is architecturally not good.
To solve this I tried to create a procedure
in type t_parameters_base
, which is calling those routines, to implement something like this (C++ syntax):
class t_parameters_base {
virtual void main_func() {
func_some_calc1(this)
func_some_calc2(this)
}
}
class t_parameters_problem1: public t_parameters_base {
virtual void main_func() {
t_parameters_base::main_func();
func_some_calc3_problem1(this);
}
}
But the problem is that those routines are using an input parameter of this type, which leads to circular dependency. How is it possible to solve this problem?
Update: Note that I really want to keep the implementation of func_some_calc1
and func_some_calc2
in different files (modulus/classes) as they implement very different logic using some private functions from their classes.
module parameters_base
type, public :: t_parameters_base
integer :: n
end type t_parameters_base
end module parameters_base
module parameters_problem1
use parameters_base
implicit none
type, extends(t_parameters_base), public :: t_parameters_problem1
integer :: p1
end type t_parameters_problem1
end module parameters_problem1
module parameters_problem2
use parameters_base
implicit none
type, extends(t_parameters_base), public :: t_parameters_problem2
integer :: p2
end type t_parameters_problem2
end module parameters_problem2
module some_calc1
use parameters_base
implicit none
contains
subroutine func_some_calc1(par)
class(t_parameters_base) :: par
end subroutine func_some_calc1
end module some_calc1
module some_calc2
use parameters_base
implicit none
contains
subroutine func_some_calc2(par)
class(t_parameters_base) :: par
end subroutine func_some_calc2
end module some_calc2
module some_calc3_problem1
use parameters_problem1
implicit none
contains
subroutine func_some_calc3_problem1(par)
type(t_parameters_problem1) :: par
print*, par%p1
end subroutine func_some_calc3_problem1
end module some_calc3_problem1
module some_calc3_problem2
use parameters_problem2
implicit none
contains
subroutine func_some_calc3_problem2(par)
type(t_parameters_problem2) :: par
print*, par%p2
end subroutine func_some_calc3_problem2
end module some_calc3_problem2
module main_problem1
use parameters_problem1
use some_calc1
use some_calc2
use some_calc3_problem1
implicit none
contains
subroutine main_func_problem1(par)
type(t_parameters_problem1) :: par
call func_some_calc1(par)
call func_some_calc2(par)
call func_some_calc3_problem1(par)
end subroutine main_func_problem1
end module main_problem1
module main_problem2
use parameters_problem2
use some_calc1
use some_calc2
use some_calc3_problem2
implicit none
contains
subroutine main_func_problem2(par)
type(t_parameters_problem2) :: par
call func_some_calc1(par)
call func_some_calc2(par)
call func_some_calc3_problem2(par)
end subroutine main_func_problem2
end module main_problem2
program module_test
use parameters_problem1
use parameters_problem2
use main_problem1
use main_problem2
implicit none
type(t_parameters_problem1) :: par1
type(t_parameters_problem2) :: par2
par1%p1 = 1
par2%p2 = 2
call main_func_problem1(par1)
call main_func_problem2(par2)
end program module_test
I think, what you are aiming for are polymorphic types with type bound procedures. Below you find a working example. To keep it simple, I do not have added any data to the types, but of course, that can be easily done. The routine
invokeCalc12
is only defined in the base type, but can be invoked from the derived types, and as in Fortran all methods are virtual, it will call the right methods.Note: I've seen that similar question has been posted at comp.lang.fortran, but at the moment I did not find a working example there, therefore the posting here.