Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Beginner
8 Views

Run-time modification of the dynamic type of a polymorphic object

Is it possible to change (further specialize), on-the-fly, the type of a variable to one of its extended (children) types, without resorting to a copy ?

MODULE M
IMPLICIT NONE

TYPE :: T_BOOK
    CHARACTER(LEN=:),ALLOCATABLE :: TITLE
END TYPE T_BOOK

TYPE,EXTENDS(T_BOOK) :: T_ENCYCLOPEDIA
    INTEGER :: N_VOLUMES
END TYPE T_ENCYCLOPEDIA

CLASS(T_BOOK),ALLOCATABLE :: MY_BOOK

END MODULE M

Using the example above... would it be possible to have a code that allocates first MY_BOOK to type T_BOOK; and then later on specializes MY_BOOK as actually being of type T_ENCYCLOPEDIA (while keeping its T_BOOK component values)?

This can be achieved with a temporary variable and tediously copying the values of the components of the parent type into the components of the child type... Not sure if there is another way.

0 Kudos
3 Replies
Highlighted
Black Belt Retired Employee
8 Views

No, it isn't possible. A copy is required. It doesn't have to be tedious - there is already a single component for the parent type, or you can use defined assignment.

You can, sort of, go the other way by passing something allocated as T_ENCYCLOPEDIA to an actual argument declared as CLASS_T_BOOK, but that's not what you're looking for.

0 Kudos
Highlighted
Valued Contributor III
8 Views

OP wrote:

..

Using the example above... would it be possible to have a code that allocates first MY_BOOK to type T_BOOK; and then later on specializes MY_BOOK as actually being of type T_ENCYCLOPEDIA (while keeping its T_BOOK component values)?

..

With the example in the original post, yes.  Note Fortran standard stipulates the parent type is essentially a component of the extension type with the same name as the type.  So you can use this fact along with the default structure constructor available for the types and also with intrinsic assignment facility for polymorphic objects to do the following:

program p

   use m, only : T_BOOK, T_ENCYCLOPEDIA, MY_BOOK
   
   implicit none
   
   MY_BOOK = T_BOOK( TITLE="Encyclopaedia Americana" )
   call out()
   print "(/,g0)", "Following 'MY_BOOK = T_ENCYCLOPEDIA(T_BOOK=MY_BOOK, M_VOLUMES=13)' assignment"
   ! Reconstruct the object as type T_ENCYCLOPEDIA using the values in the existing object
   MY_BOOK = T_ENCYCLOPEDIA(T_BOOK=MY_BOOK, N_VOLUMES=13)
   call out()
   
contains

   subroutine out()

      select type ( MY_BOOK )
         type is ( T_BOOK )
            print *, "MY_BOOK is of type T_BOOK and has the title:"
            print *, MY_BOOK%TITLE
         type is ( T_ENCYCLOPEDIA )
            print *, "MY_BOOK is now of type T_ENCYCLOPEDIA and has the title:"
            print *, MY_BOOK%TITLE
            print *, "with", MY_BOOK%N_VOLUMES, " volumes"
         class default
            print *, "Unknown type pf MY_BOOK"
      end select

      return
      
   end subroutine
   
end program p

With Intel Fortran 19.0 Update 4, the program output is:

 MY_BOOK is of type T_BOOK and has the title:
 Encyclopaedia Americana

 Following 'MY_BOOK = T_ENCYCLOPEDIA(T_BOOK=MY_BOOK, M_VOLUMES=13)' assignment
 MY_BOOK is now of type T_ENCYCLOPEDIA and has the title:
 Encyclopaedia Americana
 with 13  volumes

 

0 Kudos
Highlighted
Beginner
8 Views

Thank you Steve and FortranFan. I had forgotten about the feature that says that a parent type is a component of its extended types; line 11 of FortranFan's code is a great reminder. There is still a temporary copy made during that assignment, but at least I don't have to code it explicitly, ha ha.

0 Kudos