我试图隐藏真实数据类型和复杂数据类型之间的差异。在FORTRAN 2003中,我认为可以有一种方法。
目标是定义一个多态可分配数组,该类型可以在运行时决定。另外还有一个子程序,它使多态数组做一些代数(同样的方程适用于实数和复数数据)。
为了做到这一点,我做了两次尝试:
方法A:
module poly
implicit none
private
type, abstract, public :: MyType
contains
procedure, public :: Constructor
endtype MyType
type, extends(MyType), public :: MyTypeR
real(8), allocatable :: AllData(:)
endtype MyTypeR
type, extends(MyType), public :: MyTypeI
complex(8), allocatable :: AllData(:)
endtype MyTypeI
contains
subroutine Constructor(this, Nsize)
class(MyType), intent(inout) :: this
integer, intent(in) :: Nsize
select type(this)
type is(MyTypeR)
allocate(this%AllData(Nsize))
type is(MyTypeI)
allocate(this%AllData(Nsize))
endselect
endsubroutine
endmodule poly
! Algebra subroutine
module Operation
contains
subroutine Square(Array)
class(*), intent(inout) :: Array(:)
select type(Array)
class is(real(8))
Array = Array**2
class is(complex(8))
Array = Array**2
endselect
endsubroutine Square
endmodule Operation
! Main
program test
use poly
use Operation
class(MyType), allocatable :: t1, t2
integer :: i
logical :: IfComplex = .true.
if(IfComplex) then
allocate(MyTypeI::t1)
else
allocate(MyTypeR::t1)
endif
call t1%Constructor(4)
call Square(t1%AllData)
endprogram test
方法B(无限多态可分配变量):
module poly
implicit none
private
type, public :: MyType
class(*), allocatable :: AllData(:)
contains
procedure, public :: Constructor
endtype MyType
contains
subroutine Constructor(this, Nsize, IfComplex)
class(MyType), intent(inout) :: this
integer, intent(in) :: Nsize
logical, intent(in) :: IfComplex
if(IfComplex) then
allocate(complex(8)::this%AllData(Nsize))
else
allocate(real(8)::this%AllData(Nsize))
endif
endsubroutine
endmodule poly
! Same algebra subroutine
! Main
program test
use poly
use Operation
type(MyType) :: t1, t2
integer :: i
call t1%Constructor(4, .true.)
call Square(t1%AllData)
endprogram test
然后我在两种方法中都遇到了代数子程序的问题:在内部赋值语句中,变量不应该是多态的。任何建议将不胜感激。
答案 0 :(得分:5)
有一些问题。
在当前的Fortran中,您无法扩展内在类型 - 内在类型不能出现在派生类型定义中的EXTENDS说明符中。
因此,在Fortran 2008中,语言禁止假装内部类型可以是select类型构造中的祖先类型。这种禁止隐含在类型保护语句的语法规则中(TYPE IS ... CLASS IS等 - type-guard-stmt 的CLASS IS形式明确限于派生-type-spec ,它排除了使用内部类型名称),这意味着符合标准的Fortran 2008编译器应该为您的语法发出错误消息。
(Fortran 2003中没有这种限制发布,但它在后来的Fortran 2003勘误表中添加了 - 也许你的Fortran 2003编译器供应商还没有实现它。)
在Fortran 2003中,当赋值变量(equals左侧的东西)是多态的时,不允许内部赋值。分配给多态变量的功能是Fortran 2008中添加到语言中的一项功能。
上述两个问题的解决方案是在Square
子例程TYPE IS而不是CLASS IS中生成类型保护语句。
超越那个直接问题(以下是更主观的,取决于你最终计划做什么):
在第一个示例中,更典型的安排是有两个单独的非类型绑定构造函数过程,一个用于MyTypeR,另一个用于MyTypeI。然后,代数操作将是MyType父级的延迟绑定,然后扩展将适当地实现。
第二个示例中的MyType并没有真正执行有用的角色 - 您也可以直接使用可分配的无限多态对象。