Sök…


Avledad typdefinition

Fortran 2003 introducerade stöd för objektorienterad programmering. Denna funktion gör det möjligt att dra nytta av moderna programmeringstekniker. Deriverade typer definieras med följande form:

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

var,

  • attr-list - en lista med attributspecifikationer
  • namn - namnet på härledd datatyp
  • namnlista - en lista över typparametrarnam separerade med komma-tecken
  • def-stmts - en eller flera INTEGER-deklarationer av typparametrarna som nämns i namnlistan
  • komponentdefinition - en eller flera typdeklarationssatser eller procedurpekarrangivelser som definierar komponenten av härledd typ
  • procedur-del - ett CONTAINS-uttalande, valfritt följt av ett PRIVATE-uttalande, och en eller flera procedurbindande uttalanden

Exempel:

type shape
    integer :: color
end type shape

Typ Förfaranden

För att få klassliknande beteende ska typ och relaterade procedurer (subroutine och funktioner) placeras i en modul:

Exempel:

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

Senare, i en kod, kan vi använda denna Shape-klass enligt följande:

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

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

Abstrakta härledda typer

En utvidgbar härledd typ kan vara abstrakt

type, abstract :: base_type
end type

En sådan härledd typ får aldrig instanseras, till exempel av

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

men ett polymorf objekt kan ha detta som dess deklarerade typ

class(base_type), allocatable :: t1

eller

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

Abstrakta typer kan ha komponenter och typbundna procedurer

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

Proceduren def_func är en uppskjuten func_iface procedur med gränssnitt func_iface . En sådan uppskjuten typbunden procedur måste implementeras av varje förlängningstyp.

Typ förlängning

En härledd typ är utdragbar om den varken har bind attributet eller sequence . En sådan typ kan förlängas med en annan typ.

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

En polymorf variabel med deklarerad typ base_type är base_type med typen higher_type och kan ha den som dynamisk typ

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

Typkompatibilitet kommer ner genom en kedja med barn, men en typ kan bara förlänga en annan typ.

En utvidgad härledd typ ärver typbundna procedurer från överordnade, men det kan åsidosättas

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

Typ konstruktör

Anpassade konstruktörer kan göras för härledda typer genom att använda ett gränssnitt för att överbelasta typnamnet. På det här sättet kan nyckelordargument som inte motsvarar komponenter användas när du konstruerar ett objekt av den typen.

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

Det här kan användas för att skapa ett bättre API än att använda separata initialiseringsrutiner:

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
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow