Domanda

E 'attualmente possibile ignorare il costruttore struttura in Fortran? Ho visto esempi proposti come questo (come ad esempio nelle specifiche 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

Questo genera fondamentalmente un mucchio di errori dovuti a nomi di variabili ridondanti (ad esempio Errore: attributo DERIVATI dei conflitti 'MyType' con l'attributo PROCEDURA (1)). Una copia integrale della esempio FORTRAN 2003 genera errori simili. Ho provato questo in gfortran 4.4, 10.1 e 11.1 ifort e tutti producono gli stessi errori.

La mia domanda: è questo solo una caratteristica non implementata di fortran 2003? O sto attuazione del presente in modo non corretto?

Edit: ho incontrato un bug report e un announced cerotto per gfortran quanto riguarda questa edizione. Tuttavia, Ho provato con un accumulo di novembre di gcc46 senza errori fortuna e simili.

Modifica. 2: Il codice di cui sopra sembra funzionare utilizzando Intel Fortran 12.1.0

È stato utile?

Soluzione

Ho consultato il mio copia dello standard Fortran 2008. Ciò consentono di definire un'interfaccia generica con lo stesso nome di un tipo derivato. Il mio compilatore (Intel Fortran 11.1) non sarà compilare il codice anche se così ho lasciato sospettare (senza una copia dello standard a mano 2003) che questa è una caratteristica non ancora inattuate dello standard Fortran 2003.

Oltre a questo, c'è un errore nel programma. La vostra dichiarazione di funzione:

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

specifica l'esistenza e l'intento di un argomento che non è presente nella specifica funzione, che dovrebbe forse essere riscritta come:

  type(mytype) function init_mytype(i)

Altri suggerimenti

  

E 'attualmente possibile ignorare il costruttore struttura in Fortran?

No. In ogni caso, anche utilizzando il tuo approccio non è del tutto circa costruttore override. Il motivo principale è che la struttura costruttore costruttore # OOP. V'è una certa somiglianza, ma questa è solo un'altra idea.

Non è possibile utilizzare la funzione non intrinseca espressione di inizializzazione. È possibile utilizzare solo costante, array o costruttore di strutture, funzioni intrinseche, ... Per maggiori informazioni date un'occhiata alla 7.1.7 inizializzazione espressione in Fortran progetto del 2003.

Prendendo questo fatto in considerazione che completamente non capisco qual è la vera differenza tra

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

e

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

e qual è il punto di utilizzare blocco INTERFACE all'interno MODULO mymod.

Beh, onestamente parlando c'è una differenza, quella enorme - il primo modo è fuorviante. Questa funzione non è il costruttore (perché non ci sono i costruttori OOP a tutti in Fortran), è un inizializzatore.


Nel costruttore tradizionale programmazione orientata agli oggetti è responsabile di sequenza fare due cose:

  1. L'allocazione di memoria.
  2. l'inizializzazione membro.

Diamo uno sguardo ad alcuni esempi di istanziare le classi in diverse lingue.

Nel Java :

MyType mt = new MyType(1);

un fatto molto importante è nascosto - il fatto che l'oggetto è in realtà un puntatore ad una varibale di un tipo di classe. L'equivalente in C ++ sarà allocazione sul mucchio utilizzando:

MyType* mt = new MyType(1);

Ma in entrambe le lingue si può vedere che due doveri costruttore si riflettono anche a livello di sintassi. Si compone di due parti: parola nuova (assegnazione) e nome del costruttore (inizializzazione). In Objective-C la sintassi questo fatto è ancora più enfatizzato:

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

Molte volte, però, si può vedere qualche altra forma di costruttore di invocazione. Nel caso di allocazione sulla pila C ++ utilizza speciale (molto scarso) Costruzione sintassi

MyType mt(1);

che in realtà è così fuorviante che si possa semplicemente non considerarlo.

Nel Python

mt = MyType(1)

sia fatto l'oggetto è in realtà un puntatore e il fatto che l'assegnazione avvengono prima sono nascosti (a livello di sintassi). E questo metodo viene chiamato ... __init__! O_O così fuorviante. Con il ++ dissolvenze allocazione pila in confronto con quello. =)


In ogni caso, l'idea di avere costruttore nella lingua implica la capacità di fare allocazione un'inizializzazione in una dichiarazione con qualche particolare tipo di metodo. E se si pensa che questo è il modo "vero OOP" ho una brutta notizia per voi. Anche Smalltalk non ha costruttori . E 'solo una convenzione per avere un metodo new sulle classi stesse (sono oggetti Singleton di classi meta). Il Design Factory pattern viene utilizzato in molte altre lingue per raggiungere lo stesso obiettivo.

Ho letto da qualche parte che i concetti di moduli in Fortran è stato ispirato da Modula-2. E sembra che per me le caratteristiche OOP si ispirano Oberon-2 . Non ci sono i costruttori a Oberon-2 anche. Ma v'è, naturalmente, pura assegnazione con procedura predichiarati NUOVO (come ALLOCATE in Fortran, ma ALLOCATE è economico). Dopo l'assegnazione è possibile (dovrebbe in pratica) chiamare alcuni initializer, che è solo un metodo ordinario. Niente di speciale qui.

Quindi, è possibile utilizzare una sorta di fabbriche per l'inizializzazione degli oggetti. E 'quello che effettivamente ha fatto con i moduli, invece di Singletonoggetti. O è meglio dire che essi (Java / C # / ... programmatori) oggetti di uso Singleton metodi al posto delle funzioni ordinarie a causa della mancanza del più un '(nessun modulo - non c'è modo di avere funzioni ordinarie, solo metodi).

Inoltre è possibile utilizzare invece di tipo-bound sottoprogramma.

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) per this arg di init SUBROUTINE sembra essere fine. Poiché ci aspettiamo che questo metodo per essere chiamato solo una volta e subito dopo l'allocazione. Potrebbe essere una buona idea per il controllo che questa ipotesi non sarà sbagliato. Per aggiungere un po booleano bandiera LOGICAL :: inited a mytype, verifica se è .false. e impostarlo .true. alla prima inizializzazione, e fare qualcosa di diverso sul tentativo di ri-inizializzazione. Io sicuramente ricordo del filo su di esso in Google Gruppi ... io non riesco a trovarlo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top