oopfortranpolymorphismtype-bounds

How to make a type-bound polymorphic pointer point to an extended type, using a parent type-bound procedure?


I am not sure if I wrote the question title right, but I did a MWE to explain me better what I would like to do:

module prueba

type    :: basic
  class(basic),pointer  :: myself => null()
  contains
  procedure :: hello => basic_hello
end type
 
type,extends(basic)    :: complicated
  contains
  procedure :: hello => complicated_hello
end type

contains

subroutine basic_hello(a)
class(basic), target  :: a
a%myself=>a       ! <----- XXX
print *, 'I am basic'
end subroutine
 
subroutine complicated_hello(a)
class(complicated), target  :: a
call a%basic%hello()
print *, 'I am complicated'
end subroutine
            
end module

program main
use prueba
type(complicated)    :: a

call a%hello()
! Returns:  
! I am basic
! I am complicated
  
call a%myself%hello()
! Returns:
! I am basic

end program 

I would like to set the pointer a%myself in the basic level, making it polymoprhic, so then I can run any of the extended hello procedure. That is, I would like to also get "I am complicated" legend in the second call (through the pointer). This might no have sense in the MWE, but I think it actually does in my real code. Since this approach is not working, I would like to know why, and what other alternative is possible. Thank you.


Solution

  • The main reason is in the

    call a%basic%hello()
    

    that way you are passing a reference which is really type(basic) and hence the stored pointer in myself is just a pointer to that part that is of type(basic).

    You need to do the assignment

    a%myself=>a  
    

    in some context, where the a is really of dynamic type complicated even if polymorphic class(basic).

    That could be in the outer scope, where you have access to the original type(complicated) variable or you could, e.g., do

    call basic_hello(a) 
    

    instead of the call a%basic%hello().

    This passes the a that is the argument of complicated_hello(a) instead of the a%basic.