Ответ 1
Сначала несколько комментариев/ответов на ваши вопросы:
-
Вы можете объявить процедуру привязки типа
deferred
. Затем вы должны определить свою подпись (интерфейс) только без конкретной реализации. Тип, содержащий процедуруdeferred
, должен быть объявленabstract
. Такие типы не могут быть созданы. Все расширяющиеся типы должны обеспечивать реализацию для данной процедуры, если они сами не являютсяabstract
. -
Чтобы обеспечить реализацию для процедуры
deferred
в расширяющемся типе, вы просто объявляете процедуру в расширяющемся типе и предоставляете реализацию для нее. -
Вы не можете превратить общедоступную процедуру заданного типа в
generic
в расширяющемся типе. Однако вы можете определитьgeneric
уже в базовом типе и расширить его в своих производных типах. -
Атрибут
pass
устанавливается по умолчанию, так что первым аргументом процедуры будет экземпляр типа. Вы можете, однако, указать его, чтобы сделать его более явным. Кроме того, вы можете использовать его в формеPASS(ARGNAME)
для указания, какой аргумент (ARGNAME
) должен быть экземпляром. Этот аргумент не должен быть первым в процедуре.
Ниже вы найдете пример с самосохранением, который должен содержать все функции, которые вы запросили:
module basis_module
implicit none
type, abstract :: Basis
integer :: NBasis
contains
procedure(allocBasisR1Interface), deferred :: allocateBasisR1
generic :: allocateBasis => allocateBasisR1
end type Basis
interface
! Interface for real basis allocation
subroutine allocBasisR1Interface(self, array)
import
class(Basis), intent(inout) :: self
real, intent(in) :: array(:)
end subroutine allocBasisR1Interface
end interface
end module basis_module
module extension_module
use basis_module
implicit none
type, extends(Basis) :: GridBasis
contains
! Extending the mapping allocateBasis => allocateBasisR1 of
! the parent type.
generic :: allocateBasis => allocateBasisC1
procedure :: allocateBasisC1
! Implementation for the deferred procedure in Basis
procedure :: allocateBasisR1
end type GridBasis
contains
subroutine allocateBasisR1(self, array)
class(GridBasis), intent(inout) :: self
real, intent(in) :: array(:)
self%NBasis = size(array)
print *, "GridBasis:allocateBasisR1"
end subroutine allocateBasisR1
subroutine allocateBasisC1(self, array)
class(GridBasis), intent(inout) :: self
complex, intent(in) :: array(:)
self%NBasis = size(array)
print *, "GridBasis:allocateBasisC1"
end subroutine allocateBasisC1
end module extension_module
program test
use extension_module
implicit none
type(GridBasis) :: mybasis
real :: myRealArray(10)
complex :: myComplexArray(5)
call mybasis%allocateBasis(myRealArray)
call mybasis%allocateBasis(myComplexArray)
end program test