Question

Est-il possible actuellement de remplacer le constructeur de la structure en Fortran? Je l'ai vu des exemples proposés comme celui-ci (par exemple dans la spécification Fortran 2003):

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

Cela génère essentiellement un tas d'erreurs en raison de noms de variables redondantes (par exemple erreur: attribut DÉRIVÉS des conflits « MyType » avec attribut PROCEDURE à (1)). Une copie verbatim de l'exemple Fortran 2003 génère des erreurs similaires. J'ai essayé cela dans gfortran 4.4, 10.1 et 11.1 ifort et ils ont tous produit les mêmes erreurs.

Ma question: est-ce juste une caractéristique de inappliquées Fortran 2003? Ou suis-je tort application de la présente?

Edit: Je suis venu dans un rapport de bogue et un announced correctif pour gfortran en ce qui concerne cette question. Cependant, je l'ai essayé d'utiliser une version de Novembre gcc46 sans chance et des erreurs similaires.

Edit 2:. Le code ci-dessus semble fonctionner en utilisant Intel Fortran 12.1.0

Était-ce utile?

La solution

Je consultais ma copie de la norme Fortran 2008. Cela ne vous permet de définir une interface générique avec le même nom que un type dérivé. Mon compilateur (Intel Fortran 11.1) ne compilera pas le code mais si je reste suspecter (sans une copie de la norme 2003 à la main) que ceci est une caractéristique non encore inappliquées de la norme Fortran 2003.

En outre, il y a une erreur dans votre programme. Votre déclaration de fonction:

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

spécifie l'existence et à l'intention d'un argument qui ne figure pas dans la spécification de la fonction, ce qui devrait peut-être réécrite comme:

  type(mytype) function init_mytype(i)

Autres conseils

  

Est-il possible actuellement de remplacer le constructeur de la structure en Fortran?

Non. Quoi qu'il en soit, même en utilisant votre approche est tout à fait pas primordial constructeur. La principale raison est que le constructeur de la structure constructeur # POO. Il y a une certaine similitude mais cela est juste une autre idée.

Vous ne pouvez pas utiliser votre fonction non-intrinsèque dans l'expression d'initialisation. Vous ne pouvez utiliser que constante, tableau ou constructeur de la structure, les fonctions intrinsèques, ... Pour plus d'informations jeter un oeil à l'expression 7.1.7 Initialisation dans le projet de Fortran 2003.

En prenant compte de ce fait, je complètement ne comprends pas quelle est la différence réelle entre

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

et

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

et quel est le point entier d'utiliser le bloc d'interface interne MODULE mymod.

Eh bien, honnêtement, il y a une différence, l'énorme - la première façon est trompeur. Cette fonction est le constructeur (car il n'y a pas de constructeurs POO du tout en Fortran), il est un initialiseur.


Dans le constructeur POO grand public est responsable de faire successivement deux choses:

  1. L'allocation de mémoire.
  2. initialisation membres.

Jetons un coup d'oeil à quelques exemples de classes instanciation dans différentes langues.

Java :

MyType mt = new MyType(1);

un fait très important est caché - le fait que l'objet est en fait un pointeur vers une varibale d'un type de classe. L'équivalent C ++ sera allocation sur tas en utilisant:

MyType* mt = new MyType(1);

Mais dans les deux langues, on peut voir que deux fonctions de constructeur se reflètent même au niveau de la syntaxe. Il se compose de deux parties: mot-clé nouvelle (allocation) et le nom du constructeur (initialisation). Objective-C syntaxe ce fait est encore plus souligné:

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

Plusieurs fois, cependant, vous pouvez voir une autre forme d'invocation du constructeur. Dans le cas de allocation sur la pile C ++ utilise la construction d'une syntaxe spéciale (très faible)

MyType mt(1);

qui est en fait trompeur que nous ne pouvons tout simplement pas le considérer.

Python

mt = MyType(1)

à la fois le fait que l'objet est en fait un pointeur et le fait que ont lieu d'affectation d'abord sont cachés (au niveau de la syntaxe). Et cette méthode est appelée ... __init__! O_O trompeur. Les fondus de répartition de l'empilement de С par rapport à celui-là. =)


Quoi qu'il en soit, l'idée d'avoir constructeur dans la langue implique la capacité de faire l'allocation une initialisation dans une instruction en utilisant la méthode une sorte spéciale. Et si vous pensez que cela est bien « vrai POO » J'ai de mauvaises nouvelles pour vous. Même Smalltalk Nous ne connaissons constructeurs . Il a juste une convention d'avoir une méthode new sur les classes elles-mêmes (ils sont des objets singleton de méta classes). Design Pattern Factory est utilisé dans de nombreuses autres langues pour atteindre le même objectif.

Je lis quelque part que les concepts de modules Fortran a été inspiré par Modula-2. Et il me semble que pour la POO sont caractéristiques inspirées par Oberon-2 . Il n'y a pas de constructeurs dans Oberon-2 également. Mais il y a d'allocation cours pur avec procédure prédéfinition NOUVEAU (comme allouons Fortran, mais ALLOCATE est STATEMENT). Après attribution, vous pouvez (si, dans la pratique) appeler une initialiseur, qui est juste une méthode ordinaire. Rien de spécial.

Vous pouvez utiliser une sorte d'usines pour initialiser des objets. Il est en fait ce que vous avez fait à l'aide des modules au lieu de singletonobjets. Ou il est préférable de dire qu'ils (Java / C # / ... programmeurs) utilisent des méthodes objets singleton au lieu des fonctions ordinaires en raison de l'absence du plus tard un (pas de modules - aucun moyen d'avoir des fonctions ordinaires, seules les méthodes).

Vous pouvez également utiliser SUBROUTINE de type lié à la place.

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) pour arg this de init SUBROUTINE semble bien. Parce que nous nous attendons à cette méthode pour être appelée une seule fois et juste après l'attribution. Peut-être une bonne idée de contrôle que cette hypothèse ne sera pas faux. Pour ajouter un peu LOGICAL :: inited booléen drapeau mytype, vérifier si elle est .false. et le mettre à .true. lors de la première initialisation, et faire quelque chose d'autre sur tentative de ré-initialisation. Je me souviens certainement un peu de fil à ce sujet dans Google Groupes ... Je ne peux pas le trouver.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top