1

如果我们有三个具有不同派生类型的不同文件,

MyTypeMod.f90:

MODULE MyTypeMod

TYPE, ABSTRACT :: MyType
INTEGER :: Num
END TYPE MyType

CONTAINS

END MODULE MyTypeMod

MyType1Mod.f90

MODULE MyType1Mod
USE MyTypeMod,  ONLY : MyType
USE MyType2Mod, ONLY : MyType2
IMPLICIT NONE

TYPE, EXTENDS(MyType) :: MyType1
CONTAINS
PROCEDURE :: Type1EqualsType2
GENERIC :: ASSIGNMENT(=) => Type1EqualsType2
END TYPE MyType1

CONTAINS

SUBROUTINE Type1EqualsType2(Type1, Type2)
TYPE(MyType1), INTENT(OUT) :: Type1
TYPE(MyType2), INTENT(IN) :: Type2
Type1%Num = Type2%Num
END SUBROUTINE Type1EqualsType2

END MODULE MyType1Mod

MyType2Mod.f90

MODULE MyType1Mod
USE MyTypeMod,  ONLY : MyType
USE MyType1Mod, ONLY : MyType1
IMPLICIT NONE

TYPE, EXTENDS(MyType) :: MyType2
CONTAINS
PROCEDURE :: Type2EqualsType1
GENERIC :: ASSIGNMENT(=) => Type2EqualsType1
END TYPE MyType2

CONTAINS

SUBROUTINE Type2EqualsType1(Type2, Type1)
TYPE(MyType2), INTENT(OUT) :: Type2
TYPE(MyType1), INTENT(IN) :: Type1
Type2%Num = Type1%Num
END SUBROUTINE Type2EqualsType1

END MODULE MyType2Mod

在这里,在这种情况下,由于模块文件相互依赖,我无法编译程序。我可以使用 SubModules 来解决问题吗?

4

1 回答 1

2

不幸的是,不,你不能完全使用子模块做你想做的事。这是因为这两个函数Type1EqualsType2Type2EqualsType1需要两者MyType1,并且MyType2在它们的函数接口中。即使您使用子模块,这两个函数都必须在各自的模块中具有接口,因此循环依赖将保持不变。

但是,有几个可能的解决方法:

选择类型

您可以将intent(in)两个函数的参数设置为class(MyType),并且仅使用select type语句进行类型解析。这将允许您将函数定义移动到子模块并解决循环依赖关系,但也意味着您必须处理将扩展的不同类型MyType传递给函数的情况。此外,select type可能会有点慢,具体取决于您的用例。

这个代码看起来像:

MODULE MyTypeMod
  IMPLICIT NONE
  TYPE, ABSTRACT :: MyType
    INTEGER :: Num
  END TYPE MyType
END MODULE MyTypeMod

MODULE MyType1Mod
  USE MyTypeMod, ONLY : MyType
  IMPLICIT NONE
  
  TYPE, EXTENDS(MyType) :: MyType1
  CONTAINS
    PROCEDURE :: Type1EqualsType2
    GENERIC :: ASSIGNMENT(=) => Type1EqualsType2
  END TYPE
  
  interface
    module SUBROUTINE Type1EqualsType2(this, input)
      TYPE(MyType1), INTENT(OUT) :: this
      class(MyType), INTENT(IN) :: input
    END SUBROUTINE
  end interface
END MODULE

MODULE MyType2Mod
  USE MyTypeMod, ONLY : MyType
  IMPLICIT NONE
  
  TYPE, EXTENDS(MyType) :: MyType2
  CONTAINS
    PROCEDURE :: Type2EqualsType1
    GENERIC :: ASSIGNMENT(=) => Type2EqualsType1
  END TYPE
  
  interface
    module SUBROUTINE Type2EqualsType1(this, input)
      TYPE(MyType2), INTENT(OUT) :: this
      class(MyType), INTENT(IN) :: input
    END SUBROUTINE
  end interface
END MODULE

submodule (MyType1Mod) MyType1Submod
  use MyType2Mod, only : MyType2
  implicit none
contains
  module procedure MyType1EqualsMyType2
    select type(input); type is(MyType1)
      this%Num = input%Num
    type is(MyType2)
      this%Num = input%Num
    class default
      ! Some kind of error handling goes here.
    end select
  end procedure
end submodule

submodule (MyType2Mod) MyType2Submod
  use MyType1Mod, only : MyType1
  implicit none
contains
  module procedure MyType2EqualsMyType1
    select type(input); type is(MyType1)
      this%Num = input%Num
    type is(MyType2)
      this%Num = input%Num
    class default
      ! Some kind of error handling goes here.
    end select
  end procedure
end submodule

一般程序

assignment(=)您可以改为使用泛型定义替换类型绑定assignment(=)定义。这避免了运行时多态性,但意味着您必须在新模块中定义分配。

这看起来像:

MODULE MyTypeMod
  IMPLICIT NONE
  TYPE, ABSTRACT :: MyType
    INTEGER :: Num
  END TYPE MyType
END MODULE MyTypeMod

MODULE MyType1Mod
  USE MyTypeMod, ONLY : MyType
  IMPLICIT NONE
  
  TYPE, EXTENDS(MyType) :: MyType1
  END TYPE
END MODULE

MODULE MyType2Mod
  USE MyTypeMod, ONLY : MyType
  IMPLICIT NONE
  
  TYPE, EXTENDS(MyType) :: MyType2
  END TYPE
END MODULE

module MyEqualsMod
  use MyType1Mod : only MyType1
  use MyType2Mod : only MyType2
  implicit none
  
  interface assignment(=)
    module procedure MyType1EqualsMyType2
    module procedure MyType2EqualsMyType1
  end interface
contains
  subroutine MyType1EqualsMyType2(this,input)
    type(MyType1), intent(out) :: this
    type(MyType2), intent(in) :: input
    this%Num = input%Num
  end subroutine

  subroutine MyType2EqualsMyType1(this,input)
    type(MyType2), intent(out) :: this
    type(MyType1), intent(in) :: input
    this%Num = input%Num
  end subroutine
end module
于 2021-10-21T12:23:04.227 回答