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

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

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

Поскольку ребенок не абстрактный, его фу (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 ответ

Решение

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

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

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

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

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

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

Другие вопросы по тегам