Fortran
Objektorienterad programmering
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)