I am trying to understand the object-oriented concepts in Fortran 2003 standards (or later). I have some knowledge in C++ so I think there are some common ideas between these tw
First some comments/answers to your questions:
You can declare a type bound procedure being deferred
. Then you have to define its signature (interface) only without a specific implementation. The type containing the deferred
procedure must be declared abstract
. Such types can not be instantiated. All extending types must provide an implementation for the given procedure, unless they are themselves abstract
.
In order to provide an implementation for a deferred
procedure in an extending type, you just declare the procedure in the extending type and provide an implementation for it.
You can not turn a public procedure of a given type into a generic
in an extending type. You can, however, define a generic
already in the base type and extend it in its derived types.
The pass
attribute is set by default, so that the first argument of the procedure will be the type instance. You can, however, specify it to make it more explicit. Additionally, you could use it in the form PASS(ARGNAME)
to specify, which argument (ARGNAME
) should be the instance. This argument needs not be the first one in the procedure.
Below you find a self containing example, which should contain all the features you asked for:
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