Is it currently possible to override the structure constructor in Fortran?
Nº todos modos incluso el uso de su enfoque no se trata de la anulación de constructores. La razón principal es que constructor de estructura # OOP constructor. Hay algunas similitudes, pero esta es solo otra idea.
No puede usar su función no intrínseca en la expresión de inicialización. Puede usar solo constante, matriz o constructor de estructura, funciones intrínsecas, ... Para obtener más información, consulte 7.1.7 Expresión de inicialización en el borrador de Fortran 2003.
Teniendo en cuenta ese hecho estoy totalmente de no entiendo cuál es la diferencia real entre
type(mytype) :: x
x = mytype(0)
y
type(mytype) :: x
x = init_mytype(0)
y lo que es el punto entero de usar interfaz de bloque dentro MÓDULO mimodelo.
Bueno, honestamente hablando hay una diferencia, la enorme: la primera es engañosa. Esta función no es el constructor (porque no hay ningún constructor de OOP en Fortran), es un inicializador.
En la corriente principal constructor de programación orientada a objetos es responsable de hacerlo secuencialmente dos cosas:
- de asignación de memoria.
- Inicialización de miembros.
Echemos un vistazo a algunos ejemplos de creación de instancias de clases en diferentes idiomas.
En Java:
MyType mt = new MyType(1);
un hecho muy importante está oculto - el hecho de que el objeto es en realidad un puntero a una varibale de un tipo de clase. El equivalente en C++ será asignación en el montón usando:
MyType* mt = new MyType(1);
Pero en ambos idiomas se puede ver que dos funciones de constructor se reflejan incluso a nivel de sintaxis. Consta de dos partes: palabra clave nueva (asignación) y nombre del constructor (inicialización). En Objective-C sintaxis este hecho se enfatiza aún más:
MyType* mt = [[MyType alloc] init:1];
Muchas veces, sin embargo, se puede ver alguna otra forma de invocación del constructor. En el caso de la asignación en la pila C++ utiliza construcción (muy pobre) sintaxis especial
MyType mt(1);
que en realidad es una interpretación errónea que simplemente no podemos considerarlo.
En Python
mt = MyType(1)
tanto el hecho de que el objeto es en realidad un puntero y el hecho de que la asignación tenga lugar primero se ocultan (a nivel de sintaxis). Y este método se llama ... __init__
! O_O Tan engañoso. La asignación de stack С ++ se desvanece en comparación con esa. =)
De todos modos, la idea de tener constructor en el lenguaje implica la capacidad de hacer asignación de una inicialización en una declaración el uso de algún tipo especial de método. Y si piensas que este es el "verdadero OOP", tengo malas noticias para ti. Incluso Smalltalkdoesn't have constructors. Es solo una convención tener un método new
en las clases en sí (son objetos únicos de metaclases). El Factory Design Pattern se usa en muchos otros idiomas para lograr el mismo objetivo.
Leí en alguna parte que los conceptos de módulos en Fortran estaban inspirados en Modula-2. Y me parece que las características de OOP están inspiradas en Oberon-2. No hay constructores en Oberon-2 también. Pero, por supuesto, hay una asignación pura con el procedimiento predeclarado NUEVO (como ALLOCATE en Fortran, pero ALLOCATE es una declaración). Después de la asignación puede (en la práctica) llamar a un inicializador, que es solo un método ordinario. Nada especial allí.
Así que puede usar algún tipo de factoría para inicializar objetos. Es lo que realmente hiciste usando módulos en lugar de objetos únicos. O es mejor decir que ellos (programadores Java/C#/...) usan métodos de objetos únicos en lugar de funciones ordinarias debido a la falta del último (no hay módulos, no hay forma de tener funciones ordinarias, solo métodos).
También puede usar SUBRUTINES con texto en su lugar.
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)
para this
arg de init
SUBRUTINA parece estar bien. Porque esperamos que este método se invoque solo una vez e inmediatamente después de la asignación. Puede ser una buena idea controlar que esta suposición no sea incorrecta. Para agregar un indicador booleano LOGICAL :: inited
a mytype
, compruebe si es .false.
y configúrelo en .true.
con la primera inicialización, y haga algo más cuando intente reinicializar. Definitivamente recuerdo algún hilo al respecto en Google Groups ... No puedo encontrarlo.
gracias, fijo. Disculpas por el error que distrae, fue un ejemplo apresurado. –