运行时由用户指定变量类型的Fortran程序实现问题
Fortran运行时动态类型变量实现方案
核心思路:多态类型+通用接口封装运算逻辑
Fortran是静态类型语言,无法让抽象基类直接持有不同类型的val,但可以通过扩展抽象基类分别实现实型、复型的存储逻辑,再用通用接口统一运算操作,彻底避免重复编写select type分支。
具体实现代码
1. 定义抽象基类与扩展类型
module number_mod implicit none ! 抽象基类:仅定义接口规范,不存储数据 type, abstract :: number_t contains procedure(abs_interface), deferred :: abs_val procedure(square_interface), deferred :: square generic :: operator(**) => square ! 重载幂运算符(此处仅实现平方) end type number_t ! 实型扩展类型:存储实型值并实现运算 type, extends(number_t) :: real_number_t real :: val contains procedure :: abs_val => real_abs procedure :: square => real_square end type real_number_t ! 复型扩展类型:存储复型值并实现运算 type, extends(number_t) :: complex_number_t complex :: val contains procedure :: abs_val => complex_abs procedure :: square => complex_square end type complex_number_t ! 延迟绑定的接口定义 abstract interface function abs_interface(this) result(res) import :: number_t class(number_t), intent(in) :: this real :: res end function abs_interface function square_interface(this, power) result(res) import :: number_t class(number_t), intent(in) :: this integer, intent(in) :: power class(number_t), allocatable :: res end function square_interface end interface contains ! 实型绝对值实现 function real_abs(this) result(res) class(real_number_t), intent(in) :: this real :: res res = abs(this%val) end function real_abs ! 实型平方实现 function real_square(this, power) result(res) class(real_number_t), intent(in) :: this integer, intent(in) :: power class(number_t), allocatable :: res allocate(real_number_t :: res) select type(res) type is(real_number_t) res%val = this%val ** power end select end function real_square ! 复型绝对值实现 function complex_abs(this) result(res) class(complex_number_t), intent(in) :: this real :: res res = abs(this%val) end function complex_abs ! 复型平方实现 function complex_square(this, power) result(res) class(complex_number_t), intent(in) :: this integer, intent(in) :: power class(number_t), allocatable :: res allocate(complex_number_t :: res) select type(res) type is(complex_number_t) res%val = this%val ** power end select end function complex_square end module number_mod
2. 主程序:运行时切换类型
program dynamic_number use number_mod implicit none class(number_t), allocatable :: num logical :: is_complex real :: r_input complex :: c_input ! 模拟用户选择变量类型 print *, "是否使用复型变量?(输入.TRUE.或.FALSE.)" read *, is_complex ! 根据用户选择实例化对应类型 if (is_complex) then print *, "输入复型变量(格式:(a,b)):" read *, c_input allocate(complex_number_t :: num) select type(num) type is(complex_number_t) num%val = c_input end select else print *, "输入实型变量:" read *, r_input allocate(real_number_t :: num) select type(num) type is(real_number_t) num%val = r_input end select end if ! 直接调用统一接口,无需重复判断类型 print *, "变量值:" select type(num) type is(real_number_t) print *, num%val type is(complex_number_t) print *, num%val end select print *, "绝对值:", num%abs_val() print *, "平方值:" select type(sq => num**2) type is(real_number_t) print *, sq%val type is(complex_number_t) print *, sq%val end select end program dynamic_number
关键优势
- 无代码重复:运算逻辑(平方、绝对值)仅在各自扩展类型中实现一次,主程序通过多态类型直接调用,无需重复编写
select type分支。 - 运行时动态切换:通过
allocate结合用户输入的布尔值实例化对应类型,无需编译多个二进制文件。 - 原生语法体验:通过运算符重载实现
num**2这类原生写法,无需额外判断包裹。
简化方案(Fortran 2018关联类型)
若编译器支持Fortran 2018关联类型,可简化代码,适合运算逻辑简单的场景:
program dynamic_type_assumed implicit none class(*), allocatable :: val logical :: is_complex real :: r complex :: c print *, "是否使用复型?(T/F)" read *, is_complex if (is_complex) then print *, "输入复型:" read *, c val = c else print *, "输入实型:" read *, r val = r end if call compute_and_print(val) contains subroutine compute_and_print(x) class(*), intent(in) :: x select type(x) type is(real) print *, "值:", x, " 平方:", x**2, " 绝对值:", abs(x) type is(complex) print *, "值:", x, " 平方:", x**2, " 绝对值:", abs(x) end select end subroutine compute_and_print end program dynamic_type_assumed
内容的提问来源于stack exchange,提问作者tmph
相关产品推荐
相关产品推荐

