Frage

Ist es derzeit möglich, die Struktur Konstruktor in Fortran außer Kraft zu setzen? Ich habe wie diese vorgeschlagene Beispiele gesehen (wie in der Fortran 2003 spec):

module mymod

  type mytype
    integer :: x
    ! Other stuff
  end type

  interface mytype
    module procedure init_mytype
  end interface

contains
  type(mytype) function init_mytype(i)
    integer, intent(in) :: i
    if(i > 0) then
      init_mytype%x = 1
    else
      init_mytype%x = 2
    end if
  end function
end

program test
  use mymod
  type(mytype) :: x
  x = mytype(0)
end program

Dies erzeugt im Wesentlichen einen Haufen von Fehlern aufgrund von redundanten Variablennamen (beispielsweise Fehler: abgeleitetes Attribut von ‚MyType‘ Konflikten mit Prozedurattribut bei (1)). Eine wortgetreue Kopie des Fortran 2003 Beispiel erzeugt ähnliche Fehler. Ich habe schon versucht, diese in gfortran 4.4, ifort 10.1 und 11.1 und alle Produkte die gleichen Fehler.

Meine Frage: ist dies nur ein unimplemented Merkmal von Fortran 2003? Oder bin ich die Umsetzung dieses falsch?

Edit: Ich habe über einen Bugreport kommen und ein announced Patch gfortran dieses Problem in Bezug auf. Allerdings habe ich versucht, eine November-Build von gcc46 ohne Glück und ähnliche Fehler verwendet wird.

Bearbeiten. 2: Der obige Code erscheint auf der Arbeit mit Intel Fortran 12.1.0

War es hilfreich?

Lösung

konsultierte ich meine Kopie der Fortran 2008-Standards. Das ermöglicht es Ihnen, eine generische Schnittstelle mit dem gleichen Namen wie ein abgeleiteten Typ zu definieren. Mein Compiler (Intel Fortran 11.1) wird der Code nicht kompiliert werden, obwohl so bin ich zu ahnen, links (ohne eine Kopie der 2003-Standard an der Hand), dass dies eine bis jetzt noch nicht implementierte Funktion des Fortran 2003-Standard.

Außerdem gibt es einen Fehler in Ihrem Programm. Ihre Funktionsdeklaration:

  type(mytype) function init_mytype
    integer, intent(in) :: i

gibt die Existenz und die Absicht ein Argument, das nicht in der Funktionsspezifikation ist, die vielleicht neu geschrieben werden sollten:

  type(mytype) function init_mytype(i)

Andere Tipps

  

Ist es derzeit möglich, die Struktur Konstruktor in Fortran außer Kraft zu setzen?

Nein. Auf jeden Fall auch Ihren Ansatz ist nicht vollständig über Konstruktor überschreiben. Der Hauptgrund ist, dass Struktur Konstruktor # OOP-Konstruktor. Es besteht eine gewisse Ähnlichkeit, aber das ist nur eine andere Idee.

Sie können nicht Ihre nicht-eigene Funktion in Initialisierungsausdruck verwenden. Sie können nur konstant, Array oder Struktur Konstruktor intrinsische Funktionen verwenden, ... Weitere Informationen finden Sie aktuelle 7.1.7 Initialisierungsausdruck in Fortran 2003 Entwurf.

diese Tatsache Berücksichtigung Ich verstehe nicht vollständig, was ist der Unterschied zwischen

type(mytype) :: x
x = mytype(0)

und

type(mytype) :: x
x = init_mytype(0)

und was ist der Sinn der INTERFACE Block innerhalb mymod Modul.

Nun, ehrlich gesagt gibt es einen Unterschied, die riesigen ein - der erste Weg ist irreführend. Diese Funktion ist nicht der Konstruktor ist (weil es überhaupt in Fortran sind keine OOP Konstruktoren), es ist ein initializer.


Im Mainstream OOP Konstruktor ist verantwortlich für die sequenziell zwei Dinge zu tun:

  1. Speicherzuweisung.
  2. Mitglied der Initialisierung.

nehmen Lassen Sie uns einen Blick auf einige Beispiele von Klassen in verschiedenen Sprachen instanziieren.

Java :

MyType mt = new MyType(1);

eine sehr wichtige Tatsache ist versteckt - die Tatsache, das Objekt ist eigentlich ein Zeiger auf eine Varibale eines Klassentypen. Das Äquivalent in C ++ wird Zuordnung auf Heap mit:

MyType* mt = new MyType(1);

Aber in beiden Sprachen kann man sehen, dass zwei Konstruktor Aufgaben auch bei Syntax-Ebene widerspiegeln. Es besteht aus zwei Teilen: Stichwort neue (Allokation) und Konstruktor Namen (Initialisierung). In Objective-C Syntax wird diese Tatsache noch mehr betont:

MyType* mt = [[MyType alloc] init:1];

Viele Male, können Sie jedoch eine andere Form der Konstruktor Aufruf sehen. Im Fall von Zuordnung auf Stapel C ++ verwendet spezieller (sehr schlecht) Syntax Aufbau

MyType mt(1);

, die tatsächlich so irreführend ist, dass wir einfach nicht in Betracht ziehen.

In Python

mt = MyType(1)

sowohl die Tatsache, das Objekt tatsächlich ein Zeiger und die Tatsache, dass die Zuteilung erfolgt erstes (bei Syntax-Ebene) versteckt sind. Und diese Methode wird aufgerufen, ... __init__! O_O So irreführend. ? ++ Stapel Zuordnung Blendungen im Vergleich zu diesen. =)


Wie auch immer, die Idee von Konstruktor in der Sprache bedeutet die Fähigkeit zu tun, Zuordnung eine Initialisierung in einer Anweisung eine besondere Art von Verfahren. Und wenn Sie denken, dass dies „wahre OOP“ Art, wie ich für Sie schlechte Nachrichten. Auch Smalltalk hat nicht Konstrukteuren . Es nur eine Konvention eine new Methode auf Klassen haben sich (sie Singleton Objekte von Meta-Klassen). Die Factory Design Pattern ist in vielen anderen Sprachen verwendet, um das gleiche Ziel zu erreichen.

Ich habe irgendwo gelesen, dass Konzepte der Module in Fortran von Modula-2 inspiriert wurde. Und es scheint mir, dass OOP Features sind inspiriert von Oberon-2 . Es gibt keine Konstrukteuren in Oberon-2 auch. Aber es ist natürlich reine Zuordnung mit vordeklarierte Verfahren NEU (wie in Fortran ALLOCATE, aber ALLOCATE ist statement). Nach Zuweisung können Sie (sollte in der Praxis) einige initializer nennen, die nur eine gewöhnliche Methode. Nichts Besonderes gibt.

So können Sie irgendeine Art von Fabriken verwenden, um Objekte zu initialisieren. Es ist, was Sie getan haben tatsächlich Module anstelle von Singleton mitObjekte. Oder ist es besser zu sagen, dass sie (Java / C # / ... Programmierer) Verwendung Singleton-Objekte Methoden anstelle von gewöhnlichen Funktionen aufgrund des Fehlens der später ein (keine Module - keine Möglichkeit, normale Funktionen haben, nur Methoden).

Sie können auch typgebundene SUBROUTINE stattdessen verwenden.

MODULE mymod

  TYPE mytype
    PRIVATE
    INTEGER :: x
    CONTAINS
    PROCEDURE, PASS :: init
  END TYPE

CONTAINS

  SUBROUTINE init(this, i)
    CLASS(mytype), INTENT(OUT) :: this
    INTEGER, INTENT(IN) :: i

    IF(i > 0) THEN
      this%x = 1
    ELSE
      this%x = 2
    END IF
  END SUBROUTINE init

END

PROGRAM test

  USE mymod

  TYPE(mytype) :: x

  CALL x%init(1)

END PROGRAM

INTENT(OUT) für this arg von init SUBROUTINE scheint in Ordnung zu sein. Weil wir diese Methode zu erwarten nur einmal aufgerufen und direkt nach der Zuteilung. Könnte eine gute Idee, Kontrolle, dass diese Annahme nicht falsch sein. Um etwas boolean flag LOGICAL :: inited zu mytype hinzuzufügen, zu überprüfen, ob es .false. ist und setzen Sie ihn auf .true. bei der ersten Initialisierung, und etwas anderes tun zu Versuch Neuinitialisierung. Ich erinnere mich, auf jeden Fall einige Thread über sie in Google Groups ... Ich kann es nicht finden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top