Home > Enterprise >  OOP Fortran, derived types and objects defined within modules: are there any cons?
OOP Fortran, derived types and objects defined within modules: are there any cons?

Time:04-22

Here's a simple Fortran95 code that GNU Fortran (gfortran) compiles very well:

    Module Module1
        Implicit None

        Type MyType
            Real(Kind=8) :: x, y
            Integer :: n
        End Type

        Contains

        Real(Kind=8) Function Calc(self)
            Type(MyType) :: self
            Calc = self%x**self%n   self%y**self%n
        End Function
    End Module
    
    Program Main
        Use Module1

        Implicit None

        Type(MyType) :: A
        
        A = MyType(3.0, 4.0, 2)

        Write(*,*) Calc(A)
    End Program Main

In this case, an object A of the derived type MyType is created and initialized inside Main. Calc() is called and its result printed. Now comes a slightly different code:

    Module Module1
        Implicit None

        Type MyType
            Real(Kind=8) :: x, y
            Integer :: n
        End Type

        Type(MyType) :: A

        Contains

        Real(Kind=8) Function Calc(self)
            Type(MyType) :: self
            Calc = self%x**self%n   self%y**self%n
        End Function
    End Module
    
    Program Main
        Use Module1

        Implicit None

        A = MyType(3.0, 4.0, 2)

        Write(*,*) Calc(A)
    End Program Main

Same number of lines, same result. But here A was assigned to the derived type MyType within Module1, and "travels" with it anytime this module is imported/used (Use) by any other module and therefore A can be used within this latter module (provided A had been previously initialized, of course). Works similarly to a global variable, but not quite; modules that don't USE Module1 cannot access A.

The question is: is there any conceptual problem with this programming "style"? One must, of course, be careful with whatever is done with A in other modules, but this applies to other variables as well.

I can see a few advantages in the use of these "travelling" objects, but I may be missing something.

CodePudding user response:

In your first example, A is a local variable, but in your second example, A is a global variable. There are many reasons why global variables are often a bad idea, explained in depth in various places around Stack Overflow 1 2 3 and Stack Exchange 4.

To give a concrete example, consider the code:

module module2
  use module1
  implicit none
contains
  subroutine foo()
    A = MyType(1.0, 2.0, 3)
    write(*,*) calc(A)
  end subroutine
end module

module module3
  use module2
  implicit none
contains
  subroutine bar()
    A = MyType(2.0, 3.0, 3)
    call foo()
    write(*,*) calc(A)
  end subroutine
end module

program main
  use module3
  implicit none

  call bar()
end program main

Rather than printing

9.0
35.0

as might be expected, this instead prints

9.0
9.0

Since any change to A is necessarily a side effect, these kinds of problems are likely to be very hard to avoid. Note also that module3 does not explicitly use module1, but rather implicitly uses module1 via use module2.

  • Related