Я пытаюсь создать размещаемый массив с элементами c полиморфи. Ниже приведен минимальный пример:
program PolyArray
implicit none
type basetype
integer :: ib
end type basetype
type, extends(basetype) :: exttype1
real :: r1
end type exttype1
type, extends(exttype1) :: exttype2
real :: r2
end type exttype2
type arraytype
class(basetype), allocatable :: comp
end type arraytype
type(arraytype), dimension(:), allocatable :: ary
integer :: N, i
N = 5
allocate (ary(N))
do i=1,N; if (mod(i,2)==0) then
allocate(exttype2::ary(i)%comp)
else if ( i==1) then
allocate(basetype::ary(i)%comp)
else
allocate(exttype1::ary(i)%comp)
end if; end do
do i=1,N; select type (this=>ary(i)%comp)
type is (basetype)
write(*,*) i, "is basetype"!, "%ib =", ary(i)%comp%ib
type is (exttype1)
write(*,*) i, "is exttype1"!, "%r1 =", ary(i)%comp%r1
type is (exttype2)
write(*,*) i, "is exttype2"!, "%r2 =", ary(i)%comp%r2
class default
write(*,*) i, "is unknown type !"
end select; end do
end program PolyArray
Теперь приведенный выше код работает нормально и выводит на печать (как и ожидалось):
1 is basetype
2 is exttype2
3 is exttype1
4 is exttype2
5 is exttype1
Однако проблема заключается в том, что когда я пытаюсь Получив доступ к компоненту каждого расширенного типа (например, r1
из exttype1
), раскомментировав закомментированную часть каждой строки write(*,*)
, мой компилятор (gfortran 7.5.0) выдает следующую ошибку:
write(*,*) i, "is exttype1", "%r1 =", ary(i)%comp%r1
1
Error: 'r1' at (1) is not a member of the 'basetype' structure
poly.f90:40:60:
write(*,*) i, "is exttype2", "%r2 =", ary(i)%comp%r2
1
Error: 'r2' at (1) is not a member of the 'basetype' structure
Я не понимаю, почему возникают эти ошибки, поскольку компилятор явно распознает расширенные типы exttype1
и exttype2
. Как правильно получить доступ к r1
и r2
?
РЕДАКТИРОВАТЬ: При изменении ary(i)%comp
на this
в каждой строке write(*,*)
код компилируется нормально. Какая разница эта модификация? Как эти два НЕ эквивалентны?