Zum Inhalt springen

Fortran: Fortran 2003: OOP

Aus Wikibooks
<<< zur Fortran-Startseite
<< Fortran 2003 Bibliotheken >>
< Intrinsische Module Submodules >


Siehe zu diesem Thema als Einführung insbesondere auch die Kapitel Fortran: Fortran 95: Datenverbund und Fortran: Fortran 95: Module und OOP. Zur Erklärung der nachfolgenden Grafiken sei auf das  Klassendiagramm der  UML verwiesen.

Klassen und Objekte

[Bearbeiten]

Es soll eine Klasse namens Haustier erstellt werden. Diese Klasse enthält als Attribut (oder Datenelement) eine Zeichenkette namens gebruell und als Operation (oder Methode) haustierPrint. Attribute und Operationen werden mittels Datenverbund eingebunden. Im Hauptprogramm wird ein Objekt ht erstellt und über dieses Objekt eine Ausgabe erzeugt.

Fortran 2003 (oder neuer)-Code
module KlasseHaustier
  implicit none

  type :: Haustier
    character(20) :: gebruell = "Uaaarg"

  contains
    procedure :: haustierPrint
  end type Haustier

contains
  subroutine haustierPrint(this)
    class(Haustier), intent(in) :: this
    print *, this%gebruell
  end subroutine haustierPrint
end module KlasseHaustier

program hauptprogramm
  use KlasseHaustier
  implicit none

  type(Haustier) :: ht

  call ht%haustierPrint   ! Ausgabe: Uaaarg
end program hauptprogramm

Der Konstruktor

[Bearbeiten]
Fortran 2003 (oder neuer)-Code
module KlasseHaustier
  implicit none

  type :: Haustier
    character(20) :: gebruell = "Uaaarg"
    integer       :: beine    = 4

  contains
    procedure :: haustierPrint
  end type Haustier

contains
  subroutine haustierPrint(this)
    class(Haustier), intent(in) :: this
    print *, this%gebruell, this%beine
  end subroutine haustierPrint
end module KlasseHaustier

program hauptprogramm
  use KlasseHaustier
  implicit none

  type(Haustier) :: ht1, ht2, ht3, ht4

  ht1 = Haustier("Brrr", 2)  ! Aufruf des Konstruktors
  ht2 = Haustier(beine = 3, gebruell = "Piep")  ! ein anderer Aufruf des Konstruktors
  ht3 = Haustier(beine = 5)  ! noch ein anderer Aufruf des Konstruktors
  ht4 = Haustier()  ! noch ein anderer Aufruf des Konstruktors

  call ht1%haustierPrint()  ! Ausgabe: Brrr         2
  call ht2%haustierPrint()  ! Ausgabe: Piep         3
  call ht3%haustierPrint()  ! Ausgabe: Uaaarg       5
  call ht4%haustierPrint()  ! Ausgabe: Uaaarg       4
end program hauptprogramm

Generalisierung

[Bearbeiten]

Hier wird die Vererbung einer Klasse (die sogenannte Generalisierung oder "is-a"-Beziehung) behandelt. Fortran 2003 unterstützt nur Einfachvererbung mittels dem Schlüsselwort extends. Hierbei werden Datenelemente und Methoden einer Superklasse an ihre Subklassen vererbt.

Fortran 2003 (oder neuer)-Code
module HaustierKlasse
  implicit none
 
  type :: Haustier
    character( 20 ) :: gebruell    = "Uaaarg"
    integer         :: beine       = 2
  end type Haustier
end module HaustierKlasse 

module HundKlasse
  use HaustierKlasse
  implicit none

  type, extends( Haustier ) :: Hund
  end type Hund  
end module HundKlasse

program hauptprogramm
  use HundKlasse
  implicit none

  type( Hund ) :: hu

  hu = Hund("Wauwau", 4)
  print *, hu           ! Ausgabe: Wauwau          4
end program hauptprogramm

Datenkapselung

[Bearbeiten]

Das Modul ist der Ort der Datenkapselung.

  • public: auch Code außerhalb des Moduls hat Schreib- und Lesezugriff (dies ist, wenn kein anderer Zugriffsmodifizierer angegeben ist, standardmäßig aktiviert)
  • public, protected: Code außerhalb des Moduls hat Lesezugriff
  • private: Code außerhalb des Moduls hat keinen Zugriff

Ein sehr einfaches Beispiel ist:

Fortran 2003 (oder neuer)-Code
module mod
  implicit none
  private

  integer, public            :: x = 1
  integer, public, protected :: y = 2
  integer, private           :: z = 3
end module mod

program hauptprogramm
  use mod
  implicit none

  print *, x     ! Lesezugriff, Ausgabe:    1
  x = 10         ! Schreibzugriff
  print *, x     ! Lesezugriff, Ausgabe:   10

  print *, y     ! Lesezugriff, Ausgabe:    2
! Folgendes funktioniert nicht (kein Schreibzugriff ausserhalb des Moduls):
! y = 20

! Folgendes funktioniert nicht (kein Lese-/Schreibzugriff ausserhalb des Moduls):
! print *, z
end program hauptprogramm

Ein weiteres Beispiel ist das Haustier-Programm von oben. Das Attribut gebruell wird mit dem Zugriffsmodifizierer private versehen. Es soll nicht von außerhalb des Moduls darauf zugreifbar sein. Die Operation haustierPrint ist dagegen public. Über diese Operation erfolgt der Zugriff von außerhalb des Moduls.

Fortran 2003 (oder neuer)-Code
module KlasseHaustier
  implicit none
  private

  type, public :: Haustier
    character(20), private :: gebruell = "Uaaarg"

  contains
    procedure, public :: haustierPrint   ! oder nur: procedure :: haustierPrint
  end type Haustier

contains
  subroutine haustierPrint(this)
    class(Haustier), intent(in) :: this
    print *, this%gebruell
  end subroutine haustierPrint
end module KlasseHaustier

program hauptprogramm
  use KlasseHaustier
  implicit none

  type(Haustier) :: ht

  call ht%haustierPrint   ! Ausgabe: Uaaarg
end program hauptprogramm

Polymorphismus

[Bearbeiten]

Fortran 2003 (oder neuer)-Code
module KlasseHaustier
  implicit none

  type, abstract :: Haustier
  contains
    procedure(gebruellX), deferred :: gebruell
  end type Haustier

  interface
    subroutine gebruellX(this)
      import :: Haustier
      class(Haustier), intent(in) :: this
    end subroutine gebruellX
  end interface
end module KlasseHaustier

module KlasseHund
  use KlasseHaustier
  implicit none
  private

  type, public, extends(Haustier) :: Hund
  contains
    procedure :: gebruell
  end type Hund
contains
  subroutine gebruell(this)
    class(Hund), intent(in) :: this
    print *, "WauWau"
  end subroutine gebruell
end module KlasseHund

module KlasseKatze
  use KlasseHaustier
  implicit none
  private

  type, public, extends(Haustier) :: Katze
  contains
    procedure :: gebruell
  end type Katze
contains
  subroutine gebruell(this)
    class(Katze), intent(in) :: this
    print *, "Miau"
  end subroutine gebruell
end module KlasseKatze

program main
  use KlasseHaustier
  use KlasseHund
  use KlasseKatze
  implicit none

  class(Haustier), allocatable :: h

  allocate(h, source = Hund())
  call h%gebruell()
! Ausgabe:  WauWau
  deallocate(h)

  allocate(h, source = Katze())
  call h%gebruell()
! Ausgabe:  Miau
  deallocate(h)
end program

Der Destruktor

[Bearbeiten]

Der Destruktor wird durch das Wörtchen final eingeleitet und sieht sonst aus wie eine normale Operation. Im folgenden Beispiel wird bei der Zerstörung des Objekts nur eine Ausgabe auf der Standardausgabe erzeugt.

Fortran 2003 (oder neuer)-Code
module mod
  implicit none
  private

  type, public :: xxx
  contains
    final :: destruct
  end type xxx

contains
  subroutine destruct(this)
    type(xxx), intent(in) :: this

    print *, "Destruktoraufruf !!!"
  end subroutine destruct
end module mod

program main
  use mod
  implicit none

  class(xxx), allocatable :: x
  allocate (x,  source = xxx())
  deallocate (x)                  ! Ausgabe: Destruktoraufruf !!!
end program main

Weiterführende Literatur

[Bearbeiten]



<<< zur Fortran-Startseite
<< Fortran 2003 Bibliotheken >>
< Intrinsische Module Submodules >