很遗憾,不,您不能使用子模块完全满足您的需求。这是因为 Type1EqualsType2 和 Type2EqualsType1 两个函数都在其函数接口中需要 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