Fortran中如何重载抽象类型内声明的延迟过程init?
需求可行,实现方案如下
你的需求完全可以实现,核心是在派生类中通过类型绑定通用接口封装不同版本的init过程,同时确保其中至少有一个过程匹配基类抽象接口的原型,满足抽象类型的延迟过程实现要求。具体步骤和代码示例如下:
1. 保持基类的抽象定义不变
基类的抽象接口abstract_init定义基础版init的原型(仅接收数组大小),派生类必须实现这个版本以满足抽象类型的要求:
module base_mod implicit none abstract interface subroutine abstract_init(this, size) import :: Base_Arrays_class class(Base_Arrays_class), intent(inout) :: this integer, intent(in) :: size end subroutine abstract_init end interface type, abstract :: Base_Arrays_class contains procedure(abstract_init), deferred :: init end type Base_Arrays_class end module base_mod
2. 在派生类中定义通用接口封装重载过程
以One_Array_t为例,先实现匹配抽象接口的基础版init,再定义带初始值的重载版本,最后通过generic :: init => ...将两个过程封装为同名通用接口,覆盖基类的延迟过程:
module one_array_mod use base_mod implicit none type, extends(Base_Arrays_class) :: One_Array_t real, allocatable :: arr(:) contains procedure :: one_array_init ! 匹配抽象接口的基础版 procedure :: one_array_init2 ! 带初始值的重载版 generic :: init => one_array_init, one_array_init2 end type One_Array_t contains subroutine one_array_init(this, size) class(One_Array_t), intent(inout) :: this integer, intent(in) :: size allocate(this%arr(size)) this%arr = 0.0 ! 默认初始值 end subroutine one_array_init subroutine one_array_init2(this, size, init_val) class(One_Array_t), intent(inout) :: this integer, intent(in) :: size real, intent(in) :: init_val allocate(this%arr(size)) this%arr = init_val end subroutine one_array_init2 end module one_array_mod
3. 同理实现Two_Arrays_t的重载
按照同样逻辑,为Two_Arrays_t实现基础版和带双初始值的重载版init:
module two_arrays_mod use base_mod implicit none type, extends(Base_Arrays_class) :: Two_Arrays_t real, allocatable :: arr1(:), arr2(:) contains procedure :: two_arrays_init ! 基础版 procedure :: two_arrays_init2 ! 带双初始值的重载版 generic :: init => two_arrays_init, two_arrays_init2 end type Two_Arrays_t contains subroutine two_arrays_init(this, size) class(Two_Arrays_t), intent(inout) :: this integer, intent(in) :: size allocate(this%arr1(size), this%arr2(size)) this%arr1 = 0.0 this%arr2 = 0.0 end subroutine two_arrays_init subroutine two_arrays_init2(this, size, val1, val2) class(Two_Arrays_t), intent(inout) :: this integer, intent(in) :: size real, intent(in) :: val1, val2 allocate(this%arr1(size), this%arr2(size)) this%arr1 = val1 this%arr2 = val2 end subroutine two_arrays_init2 end module two_arrays_mod
4. 调用示例
现在可以同时调用两种版本的init,完全符合你的需求:
program test_arrays use one_array_mod use two_arrays_mod implicit none type(One_Array_t) :: one_arr type(Two_Arrays_t) :: two_arr ! 基础版调用 call one_arr%init(5) print *, "单数组默认初始化:", one_arr%arr ! 带初始值的调用 call one_arr%init(5, 4.0) print *, "单数组初始化为4:", one_arr%arr ! 基础版调用 call two_arr%init(3) print *, "双数组默认初始化:", two_arr%arr1, two_arr%arr2 ! 带双初始值的调用 call two_arr%init(3, 5.0, 8.0) print *, "双数组分别初始化为5和8:", two_arr%arr1, two_arr%arr2 end program test_arrays
为什么之前的方法不兼容?
你之前直接在派生类中绑定接口重载时,没有确保重载集合中包含匹配基类抽象接口abstract_init的过程,导致编译器无法验证派生类是否满足抽象类型的延迟过程实现要求。通过上述方式,通用接口中既包含了匹配抽象接口的基础版,又包含了重载版本,同时满足多态要求和重载调用需求。
内容的提问来源于stack exchange,提问作者Stef1611
相关产品推荐
相关产品推荐

