Is it currently possible to override the structure constructor in Fortran?
No. Anyway even using your approach is completely not about constructor overriding. The main reason is that structure constructor # OOP constructor. There is some similarity but this is just another idea.
You can not use your non-intrinsic function in initialization expression. You can use only constant, array or structure constructor, intrinsic functions, ... For more information take a look at 7.1.7 Initialization expression in Fortran 2003 draft.
Taking that fact into account I completely do not understand what is the real difference between
type(mytype) :: x
x = mytype(0)
and
type(mytype) :: x
x = init_mytype(0)
and what is the whole point of using INTERFACE block inside mymod MODULE.
Well, honestly speaking there is a difference, the huge one - the first way is misleading. This function is not the constructor (because there are no OOP constructors at all in Fortran), it is an initializer.
In mainstream OOP constructor is responsible for sequentially doing two things:
- Memory allocation.
- Member initialization.
Let's take a look at some examples of instantiating classes in different languages.
In Java:
MyType mt = new MyType(1);
a very important fact is hidden - the fact the object is actually a pointer to a varibale of a class type. The equivalent in C++ will be allocation on heap using:
MyType* mt = new MyType(1);
But in both languages one can see that two constructor duties are reflected even at syntax level. It consists of two parts: keyword new (allocation) and constructor name (initialization). In Objective-C syntax this fact is even more emphasized:
MyType* mt = [[MyType alloc] init:1];
Many times, however, you can see some other form of constructor invocation. In the case of allocation on stack C++ uses special (very poor) syntax construction
MyType mt(1);
which is actually so misleading that we can just not consider it.
In Python
mt = MyType(1)
both the fact the object is actually a pointer and the fact that allocation take place first are hidden (at syntax level). And this method is called ... __init__
! O_O So misleading. С++ stack allocation fades in comparison with that one. =)
Anyway, the idea of having constructor in the language imply the ability to do allocation an initialization in one statement using some special kind of method. And if you think that this is "true OOP" way I have bad news for you. Even Smalltalk doesn't have constructors. It just a convention to have a new
method on classes themselves (they are singleton objects of meta classes). The Factory Design Pattern is used in many other languages to achieve the same goal.
I read somewhere that concepts of modules in Fortran was inspired by Modula-2. And it seems for me that OOP features are inspired by Oberon-2. There is no constructors in Oberon-2 also. But there is of course pure allocation with predeclared procedure NEW (like ALLOCATE in Fortran, but ALLOCATE is statement). After allocation you can (should in practice) call some initializer, which is just an ordinary method. Nothing special there.
So you can use some sort of factories to initialize objects. It's what you actually did using modules instead of singleton objects. Or it's better to say that they (Java/C#/... programmers) use singleton objects methods instead of ordinary functions due to the lack of the later one (no modules - no way to have ordinary functions, only methods).
Also you can use type-bound SUBROUTINE instead.
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)
for this
arg of init
SUBROUTINE seems to be fine. Because we expect this method to be called only once and right after allocation. Might be a good idea to control that this assumption will not be wrong. To add some boolean flag LOGICAL :: inited
to mytype
, check if it is .false.
and set it to .true.
upon first initialization, and do something else on attempt to re-initialization. I definitely remember some thread about it in Google Groups... I can not find it.