OOP Fortran,模块中定义的派生类型和对象:有什么缺点吗?

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

这是 GNU Fortran (gfortran) 编译得很好的一个简单的 Fortran95 代码:

    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

在这种情况下,派生类型 MyType 的对象 AMain 中创建并初始化。调用 Calc() 并打印其结果。现在有一个稍微不同的代码:

    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

行数相同,结果相同。但是这里 A 被分配给 Module1 内的派生类型 MyType,并且任何时候这个模块是 imported/used (Use)模块,因此 A 可以在后一个模块中使用(当然前提是 A 之前已经初始化)。与全局变量类似,但不完全相同;不使用 Module1 的模块无法访问 A.

问题是:这种编程“风格”是否存在概念上的问题?当然,无论在其他模块中用 A 做什么,都必须小心,但这也适用于其他变量。

我可以看到使用这些“旅行”对象的一些优点,但我可能会遗漏一些东西。

在您的第一个示例中,A 是一个局部变量,但在您的第二个示例中,A 是一个全局变量。全局变量通常不是一个好主意的原因有很多,在 Stack Overflow 周围的各个地方都有深入的解释 1 2 3 and Stack Exchange 4

举个具体的例子,考虑代码:

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

而不是打印

9.0
35.0

正如预期的那样,这会打印

9.0
9.0

由于对 A 的任何更改都必然是 side effect,因此此类问题可能很难避免。另请注意,module3 并未显式 use module1,而是通过 use module2.

隐式使用 module1