(j3.2006) Access to abstract part of polymorphic object of abstract base type

Van Snyder Van.Snyder
Mon Nov 9 20:46:25 EST 2015

I have an abstract base type and non-abstract extensions:

  type, abstract :: H_t ! For horizontal (lat/lon) grids; can't instantiate it
    real(rg) :: Lon     ! Longitude, Degrees
    real(rg) :: Lat     ! Latitude, Degrees
  end type H_t 

  type, extends(h_t) :: H_Geoc
  !  real(rg) :: Lon    ! Longitude, degrees
  !  real(rg) :: Lat    ! Geocentric latitude, degrees
  end type H_Geoc

  type, extends(h_t) :: H_Geod
  !  real(rg) :: Lon    ! Longitude, degrees
  !  real(rg) :: Lat    ! Geodetic latitude, degrees
  end type H_Geoc

where H_Geoc and H_Geod are standing in for nonexistent units support.

I have variables, e.g.,

  type(h_geoc) :: G1 = geoc(0.0,0.0), G2 = geoc(90.0,0.0)
  class(h_t), allocatable :: G3

I have allocated G3

  allocate ( g3, source=g1 )

I thereby know that it is allocated, and that its dynamic type is

If I assign to it using, say

  g3 = g2

there is presumably a runtime check that the types agree.  There is a
remote chance that a very clever optimizer will use a data flow analysis
to realize that the dynamic type of g3 is the same as the declared and
dynamic type of g2 and suppress the runtime check -- but I'd rather not
count on it.  This is a special case in which I know that the type of g2
has no additional components.  The more general case is that I only want
to assign the "base type" part, even though the base type is abstract.

I could "pop open" g3 using a SELECT TYPE construct with a TYPE IS
branch, but I might not know the dynamic type, and might not even know
the entire list of possible dynamic types.  I could in principle write
out individual assignments to the components of the base type, but in
more general settings there might be large numbers of them.  I might
hope to write

  g3%h_t = g2%h_t

but I cannot because g3 IS of declared type h_t, not an extension of it.

A kludge is to introduce an additional type

  type, abstract :: H_t_0
    real(rg) :: Lon     ! Degrees
    real(rg) :: Lat     ! Degrees
  end type H_t

  type, abstract, extends(h_t_0) :: H_t
  ! real(rg) :: Lon     ! Degrees
  ! real(rg) :: Lat     ! Degrees
  end type H_t

Thereby, objects of declared type H_t have a nonpolymorphic parent
component named H_t_0 of type H_t_0.

I could then assign using

  g3%h_t_0 = g2%h_t_0

To avoid such a kludge, it would be helpful if each type had a
nonpolymorphic "self" component with the same name as its type.
Presumably, it would only be used with polymorphic objects to make them
nonpolymorphic and of their declared (not dynamic) type, but that ought
not to be a requirement because some people might prefer to have the
documentary value of it.

An alternative is an extension of the ASSIGN statement proposed in

  nonpolymorphic assign ( g3 = g2%h_t )

This requires that g3 is allocated or associated if it's not a dummy
argument (else an error condition occurs), and therefore is of a dynamic
type that has an "h_t" component, which cannot be selected using g3 as a
base object.  I.e., although g3 is of abstract declared type, it is not
of abstract dynamic type, which (we hope and believe) is impossible.  It
would be interpreted in this case as a nonpolymorphic object, and
therefore the ordinary rules of nonpolymorphic type conformance apply.

More information about the J3 mailing list