I am trying to use pointers to create links between objects. Using Fortran and here is the code piece:
module base_pars_module
type,abstract,public :: base_pars
end type
end module
module test_parameters_module
use base_pars_module
type, extends(base_pars) :: test_pars
contains
procedure :: whoami
end type
contains
function whoami(this) result(iostat)
class( test_pars) :: this
write(*,*) 'i am a derived type child of base_pars'
end type
end module
module base_mask_module
use base_pars module
type, abstract , public :: base_mask
class(base_pars),pointer :: parameters
end type
end module
module test_mask_module
use base_mask_module
implicit none
type, extends(base_mask) :: test_mask
end type
end module
program driver
type(test_pars) , target :: par_Test
type(test_mask) :: mask_test
iostat= par_test%whoami()
mask_test%parameters=>par_test
iostat=mask_test%parameters%whoami()
end program
parameters
at base_mask_module
is a pointer with base_pars
class. I would like to use this pointer to refer par_test
object which is test_pars
type that extends base_pars
type. So the pointer and the target has the same class. But when I compile this it gives an error:
driver.f90:17.37:
iostat=mask_test%parameters%whoami()
1
Error: 'whoami' at (1) is not a member of the 'base_pars' structure
Is it a bug or am i doing something wrong?
When you have polymorphism like this there are two things to consider about an object: its dynamic type and its declared type. The
parameters
component oftest_mask
(base_mask
) is declared asSuch a component therefore has declared type
base_pars
.Come the pointer assignment
mask_test%parameters
has dynamic type the same aspar_test
:test_pars
. It's of declared typebase_pars
, though, and it's the declared type that is important when we care about its components and bindings.base_pars
indeed has nowhoami
.You need, then, something which has declared type
par_test
. Without changing the definitions of the derived types you can do this with theselect type
construct.That said, things get pretty tedious quite quickly with this approach. Always using
select type
, distinguishing between numerous extending types, will be quite a bind. An alternative would be to ensure that the declared typebase_pars
has a bindingwhoami
. Instead of changing the main program as above, we alter the modulebase_pars_module
:So, we've a deferred binding in
base_pars
that is later over-ridden by a binding in the extending typetest_pars
.mask_test%parameters%whoami()
in the main program is then a valid and the function called is that offered by the dynamic type ofparameters
.Both approaches here address the problem with the binding of the declared type of
parameters
. Which best suits your real-world problem depends on your overall design.If you know that your hierarchy of types will all have enough in common with the base type (that is, all will offer a
whoami
binding) then it makes sense to go for this second approach. Use the first approach rather when you have odd special cases, which I'd suggest should be rare.