Fortran - Как написать пользовательский ввод / вывод для массива разных классов с одним и тем же родителем? - PullRequest
0 голосов
/ 07 июня 2018

Мне нужно реализовать функцию, которая будет сериализовать (то есть сохранить в неформатированный двоичный файл) класс, содержащий массив объектов, принадлежащих к одному абстрактному классу, но принадлежащих нескольким различным унаследованным классам.

Дело в том, что этот массив передается моей функции и создается действиями пользователя.Итак, у меня нет возможности узнать о конкретных типах, которые хранятся в массиве.

Есть ли способ реализовать методы ввода-вывода для записи и чтения таким образом, чтобы автоматически записывать массив без необходимостиуказать типы его отдельных элементов?

Я написал этот код, чтобы проиллюстрировать мою ситуацию:

module m
    implicit none

    type :: container
        class(a), allocatable :: item
    end type container

    type, abstract :: a
        integer, public :: num
    contains
        procedure :: write_impl => write_a
        procedure :: read_impl => read_a

        generic            :: write(unformatted) => write_impl
        generic            :: read(unformatted)  => read_impl
    end type a

    type, extends(a) :: b
        integer, public :: num2
    contains
        procedure :: write_impl => write_b
        procedure :: read_impl => read_b
   end type b

    type, extends(a) :: c
    end type c

contains

    subroutine write_a(this, unit, iostat, iomsg)
        class(a), intent(in)    :: this
        integer, intent(in)         :: unit
        integer, intent(out)        :: iostat
        character(*), intent(inout) :: iomsg

        write(unit, iostat=iostat, iomsg=iomsg) this%num
    end subroutine write_a

    subroutine read_a(this, unit, iostat, iomsg)
        class(a), intent(inout) :: this
        integer, intent(in)         :: unit
        integer, intent(out)        :: iostat
        character(*), intent(inout) :: iomsg

        read(unit, iostat=iostat, iomsg=iomsg) this%num
    end subroutine read_a

    subroutine write_b(this, unit, iostat, iomsg)
        class(b), intent(in)    :: this
        integer, intent(in)         :: unit
        integer, intent(out)        :: iostat
        character(*), intent(inout) :: iomsg

        write(unit, iostat=iostat, iomsg=iomsg) this%num, this%num2
    end subroutine write_b

    subroutine read_b(this, unit, iostat, iomsg)
        class(b), intent(inout) :: this
        integer, intent(in)         :: unit
        integer, intent(out)        :: iostat
        character(*), intent(inout) :: iomsg

        read(unit, iostat=iostat, iomsg=iomsg) this%num, this%num2
    end subroutine read_b
end module m

program mwe
    use m

    implicit none

    class(a), allocatable :: o1, o2, o3
    class(container), allocatable :: arr(:)
    integer :: i

    o1 = b(1,2)
    o2 = c(3)

    allocate(arr(2))
    arr(1) = container(o1)
    arr(2) = container(o2)


    ! How to serialize 'arr' without specifying its elements' types?

end program mwe

Итак, есть ли способ, как сериализовать такой массив без необходимости вручную указывать, что o1 имеет тип b, а o2 имеет тип c?

Мне нужно иметь возможность сериализовать массив абстрактного типа a в целом, а также читать его из двоичного файла без предварительного знания его элементов.

...