(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
h_geoc.
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
15-166:
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