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, exclude extends 
  • 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. 

Derived types
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

Derived types with inheritance
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


  • No labels