Zoeken…


Afgeleide typedefinitie

Fortran 2003 introduceerde ondersteuning voor objectgeoriënteerd programmeren. Met deze functie kunt u profiteren van moderne programmeertechnieken. Afgeleide typen worden gedefinieerd met de volgende vorm:

TYPE [[, attr-list] :: ] name [(name-list)]
   [def-stmts]
   [PRIVATE statement or SEQUENCE statement]. . .
   [component-definition]. . .
   [procedure-part]
END TYPE [name]

waar,

  • attr-list - een lijst met kenmerkspecificaties
  • naam - de naam van het afgeleide gegevenstype
  • name-list - een lijst met namen van typeparameters gescheiden door komma's
  • def-stmts - een of meer INTEGER-verklaringen van de typeparameters die in de naamlijst worden genoemd
  • componentdefinitie - een of meer typeaangifte-instructies of procedure-pointerinstructies die de component van het afgeleide type definiëren
  • procedure-deel - een CONTAINS verklaring, optioneel gevolgd door een PRIVATE verklaring, en een of meer procedure bindende verklaringen

Voorbeeld:

type shape
    integer :: color
end type shape

Type procedures

Om klasse-achtig gedrag te verkrijgen, moeten het type en de bijbehorende procedures (subroutine en functies) in een module worden geplaatst:

Voorbeeld:

module MShape
    implicit none
    private

    type, public :: Shape
    private
        integer :: radius
    contains
        procedure :: set   => shape_set_radius
        procedure :: print => shape_print
    end type Shape

contains
    subroutine shape_set_radius(this, value)
        class(Shape), intent(in out) :: self
        integer, intent(in)          :: value

        self%radius = value
    end subroutine shape_set_radius

    subroutine shape_print(this)
        class(Shape), intent(in) :: self

        print *, 'Shape: r = ', self%radius
    end subroutine shape_print
end module MShape

Later kunnen we in een code deze Shape-klasse als volgt gebruiken:

! declare a variable of type Shape
type(Shape) :: shape

! call the type-bound subroutine
call shape%set(10)
call shape%print 

Abstract afgeleide types

Een uitbreidbaar afgeleid type kan abstract zijn

type, abstract :: base_type
end type

Een dergelijk afgeleid type mag nooit worden geïnstantieerd, zoals door

type(base_type) t1
allocate(type(base_type) :: t2)

maar een polymorf object kan dit als het aangegeven type hebben

class(base_type), allocatable :: t1

of

function f(t1)
  class(base_type) t1
end function

Abstracte types kunnen componenten en typegebonden procedures hebben

type, abstract :: base_type
  integer i
contains
  procedure func
  procedure(func_iface), deferred :: def_func
end type

De procedure def_func is een uitgestelde func_iface procedure met interface func_iface . Een dergelijke uitgestelde typegebonden procedure moet door elk uitbreidend type worden geïmplementeerd.

Type extensie

Een afgeleid type is uitbreidbaar als het noch het bind noch het sequence heeft. Een dergelijk type kan worden uitgebreid met een ander type.

module mod

  type base_type
    integer i
  end type base_type

  type, extends(base_type) :: higher_type
    integer j
  end type higher_type

end module mod

Een polymorfe variabele met het aangegeven type base_type is type compatibel met type higher_type en kan dat als dynamisch type hebben

class(base_type), allocatable :: obj
allocate(obj, source=higher_type(1,2))

Type compatibiliteit daalt af door een keten van kinderen, maar een type kan slechts één ander type uitbreiden.

Een uitgebreid afgeleid type neemt type-gebonden procedures over van de ouder, maar dit kan worden opgeheven

module mod

  type base_type
  contains
    procedure :: sub => sub_base
  end type base_type

  type, extends(base_type) :: higher_type
  contains
    procedure :: sub => sub_higher
  end type higher_type

contains

  subroutine sub_base(this)
    class(base_type) this
  end subroutine sub_base

  subroutine sub_higher(this)
    class(higher_type) this
  end subroutine sub_higher

end module mod

program prog
  use mod

  class(base_type), allocatable :: obj

  obj = base_type()
  call obj%sub

  obj = higher_type()
  call obj%sub

end program

Type constructor

Aangepaste constructors kunnen worden gemaakt voor afgeleide typen door een interface te gebruiken om de typenaam te overbelasten. Op deze manier kunnen trefwoordargumenten die niet overeenkomen met componenten worden gebruikt bij het construeren van een object van dat type.

module ball_mod
  implicit none

  ! only export the derived type, and not any of the
  ! constructors themselves
  private
  public :: ball

  type :: ball_t
     real :: mass
  end type ball_t

  ! Writing an interface overloading 'ball_t' allows us to
  ! overload the type constructor
  interface ball_t
     procedure :: new_ball
  end interface ball_t

contains

  type(ball_t) function new_ball(heavy)
    logical, intent(in) :: heavy

    if (heavy) then
       new_ball%mass = 100
    else
       new_ball%mass = 1
    end if
    
  end function new_ball
  
end module ball_mod

program test
  use ball_mod
  implicit none

  type(ball_t) :: football
  type(ball_t) :: boulder
  
  ! sets football%mass to 4.5
  football = ball_t(4.5)
  ! calls 'ball_mod::new_ball'
  boulder = ball_t(heavy=.true.)
end program test

Dit kan worden gebruikt om een nettere API te maken dan met afzonderlijke initialisatieroutines:

subroutine make_heavy_ball(ball)
  type(ball_t), intent(inout) :: ball
  ball%mass = 100
end subroutine make_heavy_ball

...

call make_heavy_ball(boulder)


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow