The concept of inheritance was added in the F2003 standard and is introduced by the attribute extends
.
Consider the following simple example:
module mod type base integer i end type base type, extends(base) :: extended integer j end type extended end module mod
Features
A polymorphic variable with declared type base
is type compatible with the type extended
; type compatibility descends through a chain of children. A type extension inherits all the components of its parent types, including a component that is the parent (accessed by extended%base
). Inheriting includes type bound procedures, but this can be overridden; the non_overridable
attribute blocks overriding. An extended type does not have to implement more type parameters, components, or bindings than its parent type. A type parameter or component declared in an extended type must have a different name than type parameters and components of its parent type. Type extensions are backwards compatible, because every instance of extended
is also an instance of base.
Limitations
- attributes:
bind(c)
,sequence
, excludeextends
- a type may extend only one other type
A more elaborate example
In the following example, please note that the calls to the subroutines did not change upon employing inheritance.
module ExampleModuleA implicit none type type_a character(len=:), allocatable :: n, m contains procedure sub_a, sub_m end type type_a contains subroutine sub_a(self, arg_a) class(type_a), intent(in) :: self character(len=:), allocatable, intent(out) :: arg_a arg_a = self%n//self%n end subroutine subroutine sub_m(self, arg_m) class(type_a), intent(in) :: self character(len=:), allocatable, intent(out) :: arg_m arg_m = self%n//self%m end subroutine end module ExampleModuleA module ExampleModuleB implicit none type type_b character(len=:), allocatable :: n, o contains procedure sub_a, sub_o end type type_b contains subroutine sub_a(self, arg_a) class(type_b), intent(in) :: self character(len=:), allocatable, intent(out) :: arg_a arg_a = self%n//self%n end subroutine subroutine sub_o(self, arg_o) class(type_b), intent(in) :: self character(len=:), allocatable, intent(out) :: arg_o arg_o = self%n//self%o end subroutine end module ExampleModuleB program main use ExampleModuleA use ExampleModuleB implicit none type(type_a) :: ta character(len=:), allocatable :: n, m, arg_a, arg_m type(type_b) :: tb character(len=:), allocatable :: o, arg_o ta%n = 'Nnn' ta%m = 'Mmm' tb%n = 'Nnn' tb%o = 'Ooo' call ta%sub_a(arg_a) print*, arg_a call ta%sub_m(arg_m) print*, arg_m call tb%sub_a(arg_a) print*, arg_a call tb%sub_o(arg_o) print*, arg_o end program main
module ExampleModuleC implicit none type type_c character(len=:), allocatable :: n contains procedure sub_a end type type_c type, extends(type_c) :: type_a character(len=:), allocatable :: m contains procedure sub_m end type type_a type, extends(type_c) :: type_b character(len=:), allocatable :: o contains procedure sub_o end type type_b contains subroutine sub_a(self, arg_a) class(type_c), intent(in) :: self character(len=:), allocatable, intent(out) :: arg_a arg_a = self%n//self%n end subroutine subroutine sub_m(self, arg_m) class(type_a), intent(in) :: self character(len=:), allocatable, intent(out) :: arg_m arg_m = self%n//self%m end subroutine subroutine sub_o(self, arg_o) class(type_b), intent(in) :: self character(len=:), allocatable, intent(out) :: arg_o arg_o = self%n//self%o end subroutine end module ExampleModuleC program main use ExampleModuleC implicit none type(type_c) :: tc character(len=:), allocatable :: n, arg_a type(type_a) :: ta character(len=:), allocatable :: m, arg_m type(type_b) :: tb character(len=:), allocatable :: o, arg_o ta%n = 'Nnn' ta%m = 'Mmm' tb%n = 'Nnn' tb%o = 'Ooo' call ta%sub_a(arg_a) print*, arg_a call ta%sub_m(arg_m) print*, arg_m call tb%sub_a(arg_a) print*, arg_a call tb%sub_o(arg_o) print*, arg_o end program main