Fortran: Fortran 95: Module und OOP
| <<< zur Fortran-Startseite | |
| << Fortran 95 | Fortran 2003 >> |
| < Systemroutinen | Offizielle Fortran 95-Erweiterungen > |
Module im Detail
[Bearbeiten]Die Bezeichnung des Schlüsselworts module weist schon darauf hin, dass Fortran 90/95 eine modulare Softwareentwicklung ermöglicht.
Modulare Programmierung
[Bearbeiten]Was ist modulare Programmierung? Modulare Programmierung
Das Modul-Konzept in Fortran 90/95 unterstützt diesen Ansatz vollständig. Das module-Konstrukt gliedert sich schematisch so
|
module ... |
|
|
|
end module ... |
Vor dem Datenbereich können noch einige Deklarationen (implicit none, save, etc.) eingefügt sein. Der Methodenbereich wird durch das Schlüsselwort contains angekündigt oder als Interface deklariert. Aber prinzipiell gilt, dass zusammengehörende Daten und die dazugehörenden Methoden (Unterprogramme) in einem Modul zusammengefasst werden.
Zugriffsteuerung
[Bearbeiten]Durch Angabe des Schlüsselworts private lässt sich die Sichtbarkeit von Datenelementen einschränken. Auf solcherart deklarierte Variablen läßt sich außerhalb des Moduls nicht zugreifen. public erlaubt den Zugriff auf entsprechend deklarierte Variablen auch von außerhalb. Zweiteres ist Standardverhalten und das Schlüsselwort public muss somit nicht explizit angegeben werden.
Beispiel:
| Fortran 90/95-Code (free source form) |
module mod_bsp
implicit none
save
! Datenbereich
real, private :: x = 1.2
real :: y = 9.8
contains
! Methodenbereich
real function addX (a)
real, intent (in) :: a
addX = x + a
end function addX
end module mod_bsp
program bsp
use mod_bsp
implicit none
write (*,*) "Ergebnis1 = ", addX (2.1)
write (*,*) "Ergebnis2 = ", y + 2.1
! Ausgabe:
! Ergebnis1 = 3.300000
! Ergebnis2 = 11.90000
! Folgendes geht nicht -> Fehlermeldung:
! write (*,*) "Ergebnis3 = ", x + 2.1
! 1) x ist private und somit außerhalb des Moduls nicht bekannt
! 2) auch im Hauptprogramm selbst ist kein x deklariert (implicit none,
! es wäre ohnehin nicht die gleiche Variable wie im Modul mod_bsp)
end program bsp
|
Rein formal läßt sich der Zugriff auf die Daten und/oder Methoden eines Moduls (module procedures) auch auf andere Arten einschränken, z.B.
module mod_bsp implicit none save private :: x ! , .... real :: x = 1.2, y = 9.8 ! ...
oder
module mod_bsp implicit none save private public :: y, addX ! , ... real :: x = 1.2, y = 9.8 ! ...
Datenkapselung, COMMONS-Ersatz: Module als Datenbereich
[Bearbeiten]
Module als reinen Datenbereich zu nutzen ist vor allem dann interessant, wenn aus mehreren Programmeinheiten auf die gleichen Daten zugegriffen werden muss, jedoch die zugreifenden Unterprogramme nicht wirklich modulspezifisch sind und dementsprechend nicht als Bestandteil des Moduls angelegt werden.
Beispiel:
| Fortran 90/95-Code (free source form) |
module konstanten real, parameter :: PI = 3.141593 real, parameter :: E = 2.718282 end module konstanten ! Hauptprogramm program bsp use konstanten implicit none real :: kreisflaeche write(*,*) 'PI = ', PI write(*,*) 'E = ', E write(*,*) 'Kreisflaeche fuer r=2.1 = ', kreisflaeche(2.1) call calcPiMalE end program bsp ! Unterprogramm 1 real function kreisflaeche(r) use konstanten implicit none real, intent (in) :: r kreisflaeche = r**2 * PI end function kreisflaeche ! Unterprogramm 2 subroutine calcPiMalE() use konstanten implicit none write (*,*) 'PI * E = ', PI * E end subroutine calcPiMalE ! Ausgabe: ! PI = 3.141593 ! E = 2.718282 ! Kreisflaeche fuer r=2.1 = 13.85442 ! PI * E = 8.539735 |
Datenabstraktion: Zusammenfassung von Daten und Methoden in einem Modul
[Bearbeiten]
Sind Daten und Unterprogramme als zusammengehörend zu betrachten, so ist es sinnvoll diese auch gemeinsam in einem Modul abzulegen. Ein Vorteil dabei ist, dass somit die Zugriffssteuerung gezielt eingesetzt werden kann. Moduldaten, die nicht von außerhalb des Moduls geändert werden dürfen, werden als private deklariert. Der Zugriff auf diese Daten kann dann nur noch mittels Methoden des Moduls erfolgen.
Beispiel:
| Fortran 90/95-Code (free source form) |
module kreis
implicit none
save
real, parameter :: PI = 3.141593
real, private :: r = 0.0
contains
subroutine setR(val)
real, intent(in) :: val
r = val
end subroutine setR
real function getR()
getR = r
end function getR
real function kreisflaeche()
kreisflaeche = r**2 * PI
end function kreisflaeche
end module kreis
! Hauptprogramm
program bsp
use kreis
implicit none
call setR(5.0)
write (*,*) "r = ", getR()
write (*,*) "Flaeche = ", kreisflaeche()
call sub1(5.0)
end program bsp
! Unterprogramm
subroutine sub1(val)
use kreis
implicit none
real, intent(in) :: val
call setR(val*2.56)
write (*,*) "r = ", getR()
write (*,*) "Flaeche = ", kreisflaeche()
end subroutine sub1
! Ausgabe:
! r = 5.
! Flaeche = 78.539825
! r = 12.799999
! Flaeche = 514.7185
|
Modul und Datenverbund
[Bearbeiten]
Das Schlüsselwort private darf in einem Datenverbund nur in Verbindung mit einem Modul Anwendung finden. Einerseits kann die Sichtbarkeit aller Variablen im Datenverbund eingeschränkt werden. Anderseits kann auch der Datenverbund selbst als private deklariert werden. Ein Zugriff auf derart deklarierte Datenelemente ist dann nur noch durch Unterprogramme des gleichen Moduls möglich. Standardmäßig sind sowohl Datenverbund als auch seine Einzelkomponenten, so wie alle anderen nicht zugriffsbeschränkten Datenelemente, in einem Modul öffentlich (public).
Beispiel: Öffentlicher Datenverbund
| Fortran 90/95-Code (free source form) |
module mod1
save
type :: tripel
real:: x, y, z
end type tripel
end module mod1
program bsp
use mod1
implicit none
type(tripel) :: tr = tripel(10.5, 0.0, -6.5)
write(*, *) tr
! Ausgabe:
! 10.5 0.0 -6.5
end program bsp
|
Beispiel: Öffentlicher Datenverbund mit privaten Datenelementen
| Fortran 90/95-Code (free source form) |
module mod1
save
type :: tripel
private
real:: x, y, z
end type tripel
contains
subroutine createTripel(this, valX, valY, valZ)
type(tripel) :: this
real, intent(in) :: valX, valY, valZ
this%x = valX
this%y = valY
this%z = valZ
end subroutine createTripel
subroutine writeTripel(this)
type(tripel) :: this
write(*,*) this
end subroutine writeTripel
end module mod1
program bsp
use mod1
implicit none
type(tripel) :: tr
call createTripel(tr, 10.5, 0.0, -6.5)
call writeTripel(tr)
! Ausgabe:
! 10.50000 0.000000 -6.500000
end program bsp
|
Beispiel: Privater Datenverbund
| Fortran 90/95-Code (free source form) |
module mod1
save
type, private :: tripel
real :: x = 0.0, y=0.0, z=0.0
end type tripel
type(tripel), private :: t
contains
subroutine changeTripel(valX, valY, valZ)
real, intent(in) :: valX, valY, valZ
t = tripel(valX, valY, valZ)
end subroutine changeTripel
subroutine writeTripel()
write (*,*) t
end subroutine writeTripel
end module mod1
program bsp
use mod1
implicit none
! Hier könnte z.B. keine Variable vom Typ "triple" angelegt werden, da in dieser PE nicht
! sichtbar (privater Datenverbund des Moduls mod1)
call writeTripel
! Ausgabe:
! 0.0 0.0 0.0
call changeTripel(10.5, -5.0, -3.5)
call writeTripel
! Ausgabe:
! 10.5 -5. -3.5
call unterprogramm
! Ausgabe:
! 10.5 -5. -3.5
end program bsp
subroutine unterprogramm
use mod1
call writeTripel
end subroutine unterprogramm
|
- Dieses Beispiel scheint auf den ersten Blick im Gegensatz zu den beiden vorherigen Varianten unnötige Einschränkungen aufzuweisen. Im Haupt- und Unterprogramm können keine Variablen des Typs
tripelangelegt werden. Im Modul wird immer auf die gleiche Variabletzugegriffen. Das gewählte Beispiel könnte somit als Singleton beschrieben werden. Es ist außerhalb des Moduls sichergestellt, dass immer nur ein Tripel existiert. Singletons werden auch in der objektorientierten Softwareentwicklung verwendet. Daneben sind auch andere Situationen vorstellbar, in denen sich das Konzept eines privaten Datenverbunds als nützlich erweisen kann.
Die Schnittstelle: Das Modul als Unterprogrammbibliothek
[Bearbeiten]
Ein Modul kann als Sammelstelle für Unterprogramme dienen - quasi eine Bibliothek für häufig und in verschiedenen Kontexten benötigte Prozeduren.
Vorteile:
- Ordnung
- Modul kann in eine eigenständige Datei ausgelagert werden.
- Parameter-Datentypüberprüfung.
Beispiel: Parameter-Datentypüberprüfung
| ohne Modul | mit Modul |
|---|---|
program bsp implicit none integer :: zahl = 5 call unterprogramm(zahl) end program bsp subroutine unterprogramm(a) implicit none real, intent(in) :: a write (*,*) a end subroutine unterprogramm |
module test
contains
subroutine unterprogramm(a)
implicit none
real, intent(in) :: a
write (*,*) a
end subroutine unterprogramm
end module test
program bsp
use test
implicit none
integer :: zahl = 5
call unterprogramm(zahl)
end program bsp
|
Die Datenausgabe zur Programmlaufzeit liefert jeweils einen fehlerhaften Wert. |
Bereits beim Compilieren tritt eine Fehlermeldung auf, z.B. bei g95: In file ....f90:20
call unterprogramm(zahl)
1
Error: Type mismatch in parameter 'a' at (1). Passing INTEGER(4) to REAL(4)
Das Programm lässt sich so nicht compilieren. |
Der Schnittstellenblock: interface
[Bearbeiten]Fortran 90/95 kennt das Sprachkonstrukt interface, welches sich in vielerlei Hinsicht nutzbringend verwenden läßt. Schnittstellenblöcke sind modulunabhängig verwendbar.
interface [name] [interface-Spezifikationsteil] end interface [name] |
Der interface-Spezifikationsteil beinhaltet nur diejenigen Informationen, die für die Deklaration der Schnittstelle relevant sind (z.B. Unterprogrammbezeichnung, Variablendeklaration). Die genaue Festlegung der Unterprogramme (inkl. Ausführungsteil) erfolgt dann außerhalb des Schnittstellenblocks. Ein wesentliches Merkmal des Schnittstellenblocks ist die penible Überprüfung der Unterprogrammparameterdatentypen, so wie das auch beim Einsatz von Modulen geschieht.
Beispiel: Parameter-Datentypüberprüfung
| ohne Schnittstellenblock | mit Schnittstellenblock |
|---|---|
program bsp implicit none integer :: zahl = 5 call unterprogramm(zahl) end program bsp subroutine unterprogramm(a) implicit none real, intent(in) :: a write (*,*) a end subroutine unterprogramm |
program bsp
implicit none
integer :: zahl = 5
interface
subroutine unterprogramm(a)
real, intent(in) :: a
end subroutine unterprogramm
end interface
call unterprogramm(zahl)
end program bsp
subroutine unterprogramm(a)
implicit none
real, intent(in) :: a
write (*,*) a
end subroutine unterprogramm
|
Die Datenausgabe zur Programmlaufzeit liefert jeweils einen fehlerhaften Wert. |
Bereits beim Compilieren tritt eine Fehlermeldung auf, z.B. bei gfortran: In file ....f90:15
call unterprogramm(zahl)
1
Error: Type/rank mismatch in argument 'a' at (1)
Das Programm lässt sich so nicht compilieren. |
Generische Unterprogrammschnittstelle
[Bearbeiten]Fortran 90/95 ermöglicht generische Methoden. Die im Schnittstellenblock deklarierten Unterprogramme können damit über den gleichen Unterprogrammnamen aufgerufen werden. Intern erfolgt dann der Aufruf des jeweils passenden Unterprogramms durch die Unterschiede der Datentypen der Unterprogrammparameter. Mittel zum Zweck ist der benannte Schnittstellenblock.
Beispiel:
| Fortran 90/95-Code (free source form) |
program bsp
implicit none
interface gensub
subroutine writeReal(val)
real, intent(in) ::val
end subroutine writeReal
subroutine writeInteger(val)
integer, intent(in) ::val
end subroutine writeInteger
subroutine writeCharacter(val)
character, intent(in) :: val
end subroutine writeCharacter
end interface gensub
call gensub(5.5)
call gensub(3)
call gensub("H")
call writeCharacter("X")
! Ausgabe:
! Real-Wert = 5.500000
! Integer-Wert = 3
! Zeichen = H
! Zeichen = X
end program bsp
subroutine writeReal(val)
real, intent(in) ::val
write (*,*) "Real-Wert = ", val
end subroutine writeReal
subroutine writeInteger(val)
integer, intent(in) ::val
write (*,*) "Integer-Wert = ", val
end subroutine writeInteger
subroutine writeCharacter(val)
character, intent(in) ::val
write (*,*) "Zeichen = ", val
end subroutine writeCharacter
|
Operatorüberladung
[Bearbeiten]Fortran 90/95 verwendet von Haus aus Operatorüberladung. So können z.B. Variablen arithmetischen Datentyps einfach miteinander addiert werden:
c = a + b
Dieser Ausdruck funktioniert unabhängig davon, ob die Variablen vom Typ Ganzzahl oder Gleitkommzahl sind. Und auch für Felder funktioniert diese einfache Form der Addition. Die einzelnen Feldkomponenten werden korrekt addiert. Das ist in anderen Programmiersprachen nicht selbstverständlich. Zusätzlich kann in Fortran 90/95 auch der Programmierer mit Hilfe von Schnittstellenblöcken sogenannte defined operations festlegen.
Beispiel:
| Fortran 90/95-Code (free source form) |
program bsp
implicit none
interface operator (.PLUS.)
function charAdd(c1, c2)
character, intent(in) :: c1, c2
character(len=2) :: charAdd
end function charAdd
end interface operator (.PLUS.)
! "Addition" mittels definiertem .PLUS.-Operator
write (*,*) "c1 .PLUS. c2 = ", "A" .PLUS. "B"
! oder auch mittels Funktion
write (*,*) "charAdd () = ", charAdd("A", "B")
! Ausgabe:
! c1 .PLUS. c2 = AB
! charAdd () = AB
end program bsp
function charAdd(c1, c2)
implicit none
character, intent(in) :: c1, c2
character(len=2) :: charAdd
charAdd = c1 // c2
end function charAdd
|
Beispiel: nur mit gfortran compilierbar, nicht mit g95 oder ifort
| Fortran 90/95-Code (free source form) |
module mod
type :: tripel
real x, y, z
end type
end module mod
program bsp
use mod
implicit none
interface operator (*)
function tripelMult(t1, t2)
type(tripel), intent(in) :: t1, t2
type(tripel) :: tripelMult
end function tripelMult
end interface operator (*)
! Multiplikation mittels überladenem *-Operator
write (*,*) "t1 * t2 =", tripel(2.0, 3.0, 4.0) * tripel(1.5, 0.5, 2.0)
! oder auch mittels Funktion
write (*,*) "tripelMult () =", tripelMult(tripel(2.0, 3.0, 4.0), tripel(1.5, 0.5, 2.0))
! Ausgabe:
! t1 * t2 = 3.000000 1.500000 8.000000
! tripelMult () = 3.000000 1.500000 8.000000
end program bsp
function tripelMult(t1, t2)
use mod
implicit none
type(tripel), intent(in) :: t1, t2
type(tripel) :: tripelMult
tripelMult = tripel(t1%x * t2%x, t1%y*t2%y, t1%z*t2%z)
end function tripelMult
|
Bei der Verwendung von defined operations sind jedoch einige Bedingungen zu beachten.
Neben den defined operations (interface operator) gibt es auch noch defined assignments (interface assignment) für die Überladung des Zuweisungsoperators.
Schnittstellenblock und Modul
[Bearbeiten]Beim vorigen Beispiel bestand das Problem, dass nur einer der getesteten Compiler eine ausführbare Datei zu Stande brachte. Abhilfe schaffen kann die Verlagerung des Schnittstellenblocks in das Modul unter Zuhilfenahme von module procedure.
Beispiel: Diesen Programmcode schlucken sowohl gfortran, g95 als auch ifort problemlos
| Fortran 90/95-Code (free source form) |
module mod
type :: tripel
real x, y, z
end type
interface operator (*)
module procedure tripelMult
end interface operator (*)
contains
function tripelMult(t1, t2)
implicit none
type(tripel), intent(in) :: t1, t2
type(tripel) :: tripelMult
tripelMult = tripel(t1%x * t2%x, t1%y*t2%y, t1%z*t2%z)
end function tripelMult
end module mod
program bsp
use mod
implicit none
! Multiplikation mittels überladenem *-Operator
write (*,*) "t1 * t2 =", tripel(2.0, 3.0, 4.0) * tripel(1.5, 0.5, 2.0)
! oder auch mittels Funktion
write (*,*) "tripelMult () =", tripelMult(tripel(2.0, 3.0, 4.0), tripel(1.5, 0.5, 2.0))
! Ausgabe:
! t1 * t2 = 3.000000 1.500000 8.000000
! tripelMult () = 3.000000 1.500000 8.000000
end program bsp
|
Unterprogramme: Die Übergabe optionaler und benannter Parameter
[Bearbeiten]Der Einsatz optionaler Parameter wurde bereits im Kapitel Unterprogramme abgehandelt. Zusätzlich unterstützt Fortran 90/95 auch die Verwendung von benannten Parametern (argument keywords). Dazu ist es erforderlich, dass das Unterprogramm ein explizites Interface aufweist, wie das z.B. bei Einbindung von Unterprogrammen in Module automatisch der Fall ist.
Beispiel:
| Fortran 90/95-Code (free source form) |
module m1
contains
subroutine abc( var1, var2 )
implicit none
integer, intent( in ) :: var1, var2
write( *, * ) var1, var2
end subroutine abc
end module m1
program bsp
use m1
implicit none
call abc( 12, 99 )
call abc( var2 = 99, var1 = 12 )
call abc( var2 = 12, var1 = 99 )
call abc( 12, var2 = 99 )
! call abc( var1 = 12, 99 ) ! so funktioniert das nicht
! Ausgabe:
! 12 99
! 12 99
! 99 12
! 12 99
end program bsp
|
Sonstiges
[Bearbeiten]use modulbezeichnung, only : modulelementeuse modulbezeichnung => bezeichnung
Objektorientierte Programmierung
[Bearbeiten]Modulares Programmieren reißt heutzutage niemanden mehr vom Hocker und selbst objektorientierte Konzepte sind seit spätestens Ende der 80-Jahre des vergangenen Jahrhunderts Stand der Technik. Im akademischen Bereich waren diese Dinge natürlich schon früher bekannt. Fortran hat in diesem Bereich also nie eine Vorreiterrolle inne gehabt. Nach jeweils kurzen Nachdenkphasen haben aber die Fortran-Leute unerschrocken auch in diesem Bereich nachgezogen.
Fortran bildet also aufgrund seiner langen Geschichte ein weites Spektrum der Programmierparadigmen ab: vom prozeduralen Programmieren (FORTRAN 77) über das modulare Programmieren (Fortran 90/95) hin zum objektorientierten Programmieren (Fortran 2003).
Fortran 90/95 ist keine typisch objektorientierte Sprache. Trotzdem lässt sich mit den modularen Spracheigenschaften von Fortran 90/95 bereits in weiten Bereichen Objektorientierung simulieren beziehungsweise nachbauen. Aber erst mit Fortran 2003 lässt sich wirklich komfortabel objektorientiert programmieren. Diese Fortran-Version wirbt dann auch „offiziell“ mit diesem Merkmal.
Welche Eigenschaften verbindet man typischerweise mit Objektorientierung? Da wären
- Klassen - Datenkapselung und Datenabstraktion
- Objekte
- Vererbung
- Statische Polymorphie: Überladen von Funktionen (und Operatoren)
- Run-Time-Polymorphie
Welche dieser Merkmale bietet Fortran 90/95 von Haus aus und was läßt sich relativ einfach nachbauen?
Klassen - Datenkapselung und Datenabstraktion
[Bearbeiten]Was ist eine Klasse?
Ein Fortran 90/95-Modul sieht sehr ähnlich aus wie eine Klasse in der objektorientierten Programmierung und ist dementsprechend auch Ausgangspunkt für den objektorientierten Ansatz in Fortran 90/95.
| Klasse | Fortran 90/95 | |||
|---|---|---|---|---|
|
module ... ! Datenbereich contains ! Methodenbereich end module ... |
Einen grundlegenden Mechanismus zum Schreiben objektorientierter Programme stellt Fortran 90/95 somit in Form der Module zur Verfügung. Jetzt stellt sich aber die Frage, wie diese Klasse instantiiert werden soll. Das wird im Abschnitt Objekte gezeigt.
Objekte
[Bearbeiten]Was sind Objekte? Objekt (Programmierung)
Ein einfaches Modul mit ein paar konventionellen Datenelementen und Prozeduren ist noch keine Klasse, aus der Objekte zu erzeugen wären. Dazu bedarf es noch eines Unterscheidungskriteriums zwischen den einzelnen Objekten. Dieses Unterscheidungskriterium kann, wie auch schon früher im Teilkapitel Modul und Datenverbund gezeigt, mittels Datenverbund hergestellt werden. Die Objekte werden somit nicht über den Modulnamen als Klasse angesprochen, sondern über die Datenverbund-Bezeichnung. Auch das ist keine neue Erkenntnis, sondern eine geschickte Ausnutzung eines Mechanismus, den Fortran 90/95 standardmäßig mit Modulen und Datenverbund zur Verfügung stellt.
Beispiel:

| Fortran 90/95-Code (free source form) |
module tripelClass
implicit none
save
type :: tripel
real:: x, y, z
end type tripel
contains
subroutine write(this)
type(tripel), intent(in) :: this
write(*, *) "********** Tripel **********"
write(*, *) this
end subroutine
end module tripelClass
program bsp
use tripelClass
implicit none
type(tripel) :: obj1 = tripel(1.5, 0.0, -6.5)
type(tripel) :: obj2 = tripel(2.5, 1.0, -4.5)
type(tripel) :: obj3 = tripel(3.5, 2.0, -2.5)
call write(obj1)
call write(obj2)
call write(obj3)
! Ausgabe:
! ********** Tripel **********
! 1.500000 0.000000 -6.500000
! ********** Tripel **********
! 2.500000 1.000000 -4.500000
! ********** Tripel **********
! 3.500000 2.000000 -2.500000
end program bsp
|
Weitere wichtige Elemente beim Erzeugen und Zerstören von Objekten sind in der OOP die sogenannten Konstruktoren und Destruktoren.
Was sind Konstruktoren und Destruktoren? Konstruktoren und Destruktoren
Konstruktoren und Destruktoren kennt Fortran 90/95 natürlich nicht. Im Bedarfsfall sind diese Elemente also mittels konventioneller Unterprogramme nachzubilden und dann jeweils explizit in den entsprechenden Programmabschnitten, nach Erzeugung beziehungsweise beim Abbau des jeweiligen Objektes, manuell aufzurufen.
Vererbung
[Bearbeiten]Was ist Vererbung? Vererbung (Programmierung)
Das OOP-Prinzip „Vererbung“ ist in Fortran 90/95 nur über Umwege realisierbar. Fortran 90/95 kennt konzeptionsbedingt für diesen Zweck keinen einfachen programmtechnischen Mechanismus. Nachfolgend wird anhand eines kleinen und überschaubaren Beispiels eine mögliche Lösung demonstriert.
Beispiel:

| Fortran 90/95-Code (free source form) |
module tripelClass
implicit none
save
type :: tripel
real:: x, y, z
end type tripel
contains
subroutine write(this)
type(tripel), intent(in) :: this
write(*, *) "********** Tripel **********"
write(*, *) this
end subroutine
end module tripelClass
module coordClass
use tripelClass
implicit none
save
type :: coord
type(tripel) :: tr
integer :: id
end type
contains
subroutine constructCoord(this, t, i)
implicit none
type(coord), intent(out) :: this
type(tripel), intent(in) :: t
integer :: i
this%tr = t
this%id = i
end subroutine constructCoord
subroutine writeCoord(this)
implicit none
type(coord), intent(in) :: this
write(*, "(A, I5, A)") "******************* KOORDINATE ", this%id, " *******************"
call write(this%tr)
end subroutine writeCoord
end module coordClass
program bsp
use coordClass
implicit none
type(coord) :: obj1 = coord(tripel(1.5, 0.0, -6.5), 1005)
type(coord) :: obj2 = coord(tripel(2.5, 1.0, -4.5), 1006)
type(coord) :: obj3 = coord(tripel(3.5, 2.0, -2.5), 1007)
call writeCoord(obj1)
call writeCoord(obj2)
call writeCoord(obj3)
! Ausgabe:
! ******************* KOORDINATE 1005 *******************
! ********** Tripel **********
! 1.500000 0.000000 -6.500000
! ******************* KOORDINATE 1006 *******************
! ********** Tripel **********
! 2.500000 1.000000 -4.500000
! ******************* KOORDINATE 1007 *******************
! ********** Tripel **********
! 3.500000 2.000000 -2.500000
end program bsp
|
Statische Polymorphie: Überladen von Funktionen (und Operatoren)
[Bearbeiten]Das Überladen von Funktionen und Operatoren unterstützt Fortran 90/95 wiederum standardmäßig. Diese Konzepte wurden schon in den Abschnitten
kurz erläutert.
Run-Time-Polymorphie
[Bearbeiten]Polymorphie zur Laufzeit eines Programmes ist mit den Mitteln von Fortran 90/95 nur einigermaßen aufwendig und kompliziert nachzubauen, jedoch prinzipiell möglich. Es sei zu diesem Thema auf die weiterführende Literatur verwiesen.
Ausblick
[Bearbeiten]Sind die Methoden zur Nachbildung objektorientierter Mechanismen auch in Fortan 2003 verwendbar? Prinzipiell schon, jedoch bietet Fortran 2003 bessere und erweiterte Möglichkeiten zur Behandlung dieses Themas. Dort wurde nämlich das Prinzip des Datenverbunds wesentlich erweitert. Ein type-Block kann dann neben den Datenelementen auch Unterprogramme beinhalten, das Schlüsselwort extends zwecks Vererbungmechanismus ist vorhanden, etc. Das in Fortran 90/95 als Datenbund/Struktur verwendbare type-Konstrukt wurde also in Fortran 2003 zu einer Klasse, ähnlich wie es in anderen Programmierspachen unter der Bezeichnung class bekannt ist, aufgerüstet.
Literatur
[Bearbeiten]Quellen
[Bearbeiten]Weiterführende Literatur
[Bearbeiten]- Decyk, Norton, Szymanski: Introduction to Object-Oriented Concepts Using Fortran90, 1996
- Decyk, Norton, Szymanski: How to Express C++ Concepts in Fortran90. 1997
- Decyk, Norton, Szymanski: How to Support Inheritance and Run-Time Polymorphism in Fortran90, 1998
- Decyk, Norton: A Simplified Method for Implementing Run-Time Polymorphism in Fortran95, 2004
- Decyk, Gardner: Object-Oriented Design Patterns in Fortran95, 2006
| <<< zur Fortran-Startseite | |
| << Fortran 95 | Fortran 2003 >> |
| < Systemroutinen | Offizielle Fortran 95-Erweiterungen > |