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
tripel
angelegt werden. Im Modul wird immer auf die gleiche Variablet
zugegriffen. 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 : modulelemente
use 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 > |