C/C++ and Fortran

 View Only

Object-Oriented Fortran: User-defined constructors

By Archive User posted Fri September 02, 2011 03:32 PM

  

Originally posted by: Rafik_Zurob


One of the main features of Fortran 2003 is object-orientation (OO). Derived types can now have specific and generic type-bound procedures, type-bound defined operators, type-bound defined assignment, type-bound finalizers (destructors), and type-bound user-defined derived type IO routines. For example, type base below has specific type-bound procedures find, assign, add and writef, defined operator +, type bound assignment, and a user-defined derived type IO formatted write routine:

module m
  type base
    integer, allocatable :: data(:)
  contains
    procedure :: find
    procedure :: assign
    procedure :: add
    procedure :: writef
    generic :: assignment(=) => assign
    generic :: operator(+) => add
    generic :: write(formatted) => writef
  end type
  !...
contains
  !...
end module

If you're familiar with other OO languages, you might be wondering about constructors. Were they missed in Fortran 2003?

The answer is no. Fortran 2003 has support for default and user-defined constructors. The constructors are not type-bound procedures, however. Structure constructors act as default constructors. User-defined constructors are created by defining a generic interface with the same name as the derived type they're supposed to construct. For example:

module m
  !...
  interface base
    module procedure new_base
  end interface

contains
  !...
  function new_base(i)
    integer, intent(in) :: i
    type(base) new_base

    allocate(new_base%data(i))
    new_base%data = i
  end function
  !...
end module

The interface above defines a user-defined constructor for type base. It is used in a similar way to a structure constructor. It can even take argument keywords.

use m
implicit none
type(base) b1, b2, b3
b1 = base(3)   ! calls new_base, assign
print *, b1    ! calls writef
b2 = base(i=4) ! calls new_base, assign
print *, b2    ! calls writef
b3 = b1 + b2   ! calls add, assign
print *, b3    ! calls writef
end

I've attached the full example to the files section as "constructor_example.f". To illustrate the calls, I'll use the functrace feature of the XL Fortran compiler. This feature calls a user-defined routine on entry and exit of every procedure. Default entry and exit routines are provided in the samples/functrace directory of the compiler installation.

For example, on my AIX machine:

> cc -c /usr/lpp/xlf/samples/functrace/tracing_routines.c
> xlf2003 constructor_example.f -qfunctrace tracing_routines.o
* m   === End of Compilation 1 ===
** _main   === End of Compilation 2 ===
1501-510  Compilation successful for file constructor_example.f.
> ./a.out
{ _main (constructor_example.f:103)
{ __m_NMOD_new_base (constructor_example.f:95)
} __m_NMOD_new_base (constructor_example.f:97)
{ __m_NMOD_assign (constructor_example.f:52)
} __m_NMOD_assign (constructor_example.f:53)
{ _xlfdtioproc0 (constructor_example.f:0)
{ __m_NMOD_writef (constructor_example.f:84)
} __m_NMOD_writef (constructor_example.f:89)
} _xlfdtioproc0 (constructor_example.f:0)
 3 3 3
{ __m_NMOD_new_base (constructor_example.f:95)
} __m_NMOD_new_base (constructor_example.f:97)
{ __m_NMOD_assign (constructor_example.f:52)
} __m_NMOD_assign (constructor_example.f:53)
{ _xlfdtioproc0 (constructor_example.f:0)
{ __m_NMOD_writef (constructor_example.f:84)
} __m_NMOD_writef (constructor_example.f:89)
} _xlfdtioproc0 (constructor_example.f:0)
 4 4 4 4
{ __m_NMOD_add (constructor_example.f:60)
{ __m_NMOD_assign (constructor_example.f:52)
} __m_NMOD_assign (constructor_example.f:53)
} __m_NMOD_add (constructor_example.f:74)
{ __m_NMOD_assign (constructor_example.f:52)
} __m_NMOD_assign (constructor_example.f:53)
{ _xlfdtioproc0 (constructor_example.f:0)
{ __m_NMOD_writef (constructor_example.f:84)
} __m_NMOD_writef (constructor_example.f:89)
} _xlfdtioproc0 (constructor_example.f:0)
 7 7 7 4
} _main (constructor_example.f:109)
>

Notice how new_base above was called for base(3) and base(i=4).


0 comments
0 views

Permalink