Отложенная процедура с перегрузкой с неполиморфной процедурой в 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
нужно реализовать.