Отложенная процедура с перегрузкой с неполиморфной процедурой в Fortran 2008 - PullRequest
0 голосов
/ 03 мая 2018

Возможно ли перегрузить отложенную процедуру неполиморфной процедурой?

Я хотел бы создать абстрактный класс (Parent) с процедурой (foo), которая должна быть перегружена каждым классом, который расширяет Parent. Я сталкиваюсь с проблемами, когда хочу снова расширить, например, класс (Grandchild) расширяет класс (Child), который расширяет Parent.

Поскольку Child не является абстрактным, его foo (foo_Child) должен быть полиморфным. Но тогда Grandchild наследует foo_Child, вместо того, чтобы принудительно определять foo_Grandchild. Кроме того, поскольку я не хочу, чтобы foo_Child был полиморфным, я хочу иметь возможность использовать Child -специфичные неполиморфные функции в foo_Child.

module test_module

  type, abstract :: Parent
  contains
    procedure(foo_Parent), deferred :: foo
  end type

  abstract interface
    subroutine foo_Parent(this,input)
      import Parent
      class(Parent), intent(out) :: this
      character(*),  intent(in)  :: input
    end subroutine
  end interface

  type, extends(Parent) :: Child
  contains
    procedure :: foo => foo_Child
  end type

  type, extends(Child) :: Grandchild
    ! Is not required to define foo=>foo_Grandchild.
    ! This is not the behaviour I want.
  end type

  interface Child
    module procedure new_Child
  end interface
contains

function new_Child(input) result(this)
  character(*), intent(in) :: input
  type(Child)              :: this
end function

subroutine foo_Child(this,input)
  type(Child),  intent(out) :: this ! Fails: 'this' is not polymorphic.
  character(*), intent(in)  :: input

  this = Child(input) ! Fails if type(Child) is replaced by class(Child).
end subroutine
end module

program test
  use test_module
end program

Подведем итог:

Есть ли способ сделать foo_Child неполиморфным, но и перегрузить foo_Parent? Или есть способ вызова неполиморфных функций (по крайней мере, Child=Child присваивание с неполиморфными rhs) в полиморфной процедуре? Если нет, есть ли обходной путь?

(я не хочу определять class(Child)=type(Child), но буду, если это единственный вариант).

1 Ответ

0 голосов
/ 03 мая 2018

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

Правила языка для внутреннего присваивания не допускают присваивания нераспределяемому полиморфному объекту. Это связано с тем, что обычно такое присвоение было бы ошибкой, похожей на нарезку - вы бы определили биты объекта, которые объявлены в динамическом типе rhs, но не в объявленном типе lhs.

Полиморфный объект может быть преобразован в неполиморфный объект, используя SELECT TYPE и защиту типов, соответствующую динамическому типу объекта. Вы также можете весело нарезать содержимое своего сердца посредством ассоциации аргументов - фактический полиморфный аргумент может быть связан с неполиморфным манекеном того же объявленного типа.

Для расширений можно принудительно реализовать привязку, сделав родительский тип абстрактным и сделав (или оставив) привязку отложенной (как вы уже сделали). В вашей ситуации это, возможно, требует дополнительного типа в вашей иерархии.

Parent (abstract) --> Child (abstract) +-> RealChild (concrete)
                                       |-> GrandChild (concrete)

Child в вышеприведенном может просто оставить привязку foo отложенной, или она может предоставить процедуру для этой привязки, а затем ввести новую отложенную привязку, которую RealChild и GrandChild необходимо реализовать.

...