Is it currently possible to override the structure constructor in Fortran?
No. Comunque anche l'utilizzo del tuo approccio non riguarda completamente la sostituzione del costruttore. Il motivo principale è il costruttore della struttura # OOP costruttore. C'è qualche somiglianza ma questa è solo un'altra idea.
Non è possibile utilizzare la funzione non intrinseca nell'espressione di inizializzazione. È possibile utilizzare solo costante, costruttore di strutture o struttura, funzioni intrinseche, ... Per ulteriori informazioni, consultare 7.1.7 Espressione di inizializzazione in Bozza di Fortran 2003.
Prendendo tale circostanza conto Sono completamente non comprendo 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, c'è una differenza, quella enorme: il primo modo è fuorviante. Questa funzione non è il costruttore (perché in Fortran non ci sono costruttori OOP), è un inizializzatore.
Nel costruttore OOP corrente principale è responsabile per sequenziale fare due cose:
- di allocazione della memoria.
- Inizializzazione membro.
Diamo un'occhiata ad alcuni esempi di classi di istanziazione in diverse lingue.
In 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 vede che due funzioni costruttore si riflettono anche a livello sintassi. Consiste di due parti: parola chiave nuova (allocazione) e nome costruttore (inizializzazione). In Objective-C 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 costruzione (molto scarso) sintassi
MyType mt(1);
che in realtà è così fuorviante possiamo solo non considerarlo.
In 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 è chiamato ... __init__
! O_O Quindi fuorviante. Lo stack stacking di С ++ sfuma in confronto a quello. =)
In ogni caso, l'idea di avere costruttore nella lingua implica la capacità di fare allocazione un'inizializzazione in una dichiarazione usando qualche particolare tipo di metodo. E se pensi che questo sia un modo "vero OOP", ho brutte notizie per te. Anche Smalltalkdoesn't have constructors. È solo una convenzione avere un metodo new
sulle classi stesse (sono oggetti singleton di meta-classi). Lo Factory Design Pattern è utilizzato in molti altri linguaggi per raggiungere lo stesso obiettivo.
ho letto da qualche parte che i concetti di moduli in Fortran è stato ispirato da Modula-2. E mi sembra che le funzionalità di OOP siano ispirate allo Oberon-2. Non ci sono costruttori in Oberon-2 anche. Ma naturalmente c'è una pura allocazione con la procedura predeterminata NEW (come ALLOCATE in Fortran, ma ALLOCATE è una dichiarazione). Dopo l'allocazione è possibile (dovrebbe in pratica) chiamare un inizializzatore, che è solo un metodo normale. Niente di speciale lì.
Quindi è possibile utilizzare alcune specie di fabbriche per inizializzare gli oggetti. È quello che hai effettivamente fatto usando i moduli invece degli oggetti singleton. Oppure è meglio dire che essi (programmatori Java/C#/...) usano metodi di oggetti singleton invece di funzioni ordinarie a causa della mancanza di quello successivo (nessun modulo - nessun modo per avere funzioni ordinarie, solo metodi).
Inoltre, è possibile utilizzare SUBROUTINE con tipo vincolato.
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. Perché ci aspettiamo che questo metodo venga chiamato solo una volta e subito dopo l'allocazione. Potrebbe essere una buona idea controllare che questa ipotesi non sia sbagliata. Per aggiungere qualche bandiera booleana LOGICAL :: inited
a mytype
, verificare se è .false.
e impostarlo su .true.
alla prima inizializzazione e fare qualcos'altro al tentativo di reinizializzazione. Ricordo sicuramente alcuni thread su di esso in Google Gruppi ... Non riesco a trovarlo.
grazie, risolto. Ci scusiamo per l'errore di distrazione, è stato un esempio affrettato. –