Fortran如何在抽象接口中重载过程 实现不同参数的类型初始化
实现方法
Fortran中抽象父类定义的延迟绑定(deferred procedure)要求所有子类的实现必须和抽象接口的签名完全匹配,参数个数、类型、秩都不能有差异,因此不能直接给不同子类定义不同参数个数的init绑定。最简洁合规的实现方案是使用Fortran的optional可选参数特性,把抽象接口中后两个长度参数声明为可选,在各子类的初始化实现中增加参数合法性校验即可。
第一步:修改抽象接口的init定义
将抽象init接口里的length2、length3加上optional属性,调用时这两个参数即可省略:
abstract interface subroutine abstract_init(this,length1,length2,length3) import shape_t class(shape_t), intent(inout) :: this real, intent(in) :: length1 real, intent(in), optional :: length2,length3 end subroutine abstract_init subroutine abstract_print(this) import shape_t class(shape_t), intent(in) :: this end subroutine abstract_print end interface
第二步:修改各子类的init实现
每个子类的init子例程同步将length2、length3设为可选参数,同时增加参数校验:当前子类必需的参数必须传入,非必需参数可直接忽略或增加提示。
- 线段(
line_t)初始化实现:
subroutine init_line(this,length1,length2,length3) class(line_t), intent(inout) :: this real, intent(in) :: length1 real, intent(in), optional :: length2,length3 ! 线段仅需长度参数,其余传入参数直接忽略 this%length = length1 end subroutine init_line
- 矩形(
rectangle_t)初始化实现:
subroutine init_rectangle(this,length1,length2,length3) class(rectangle_t), intent(inout) :: this real, intent(in) :: length1 real, intent(in), optional :: length2,length3 ! 校验必传宽度参数 if (.not. present(length2)) error stop "init_rectangle: 必须传入宽度参数length2" this%length = length1 this%width = length2 end subroutine init_rectangle
- 长方体(
box_t)初始化实现:
subroutine init_box(this,length1,length2,length3) class(box_t), intent(inout) :: this real, intent(in) :: length1 real, intent(in), optional :: length2,length3 ! 校验必传宽度、高度参数 if (.not. present(length2) .or. .not. present(length3)) & error stop "init_box: 必须传入宽度参数length2和高度参数length3" this%length = length1 this%width = length2 this%height = length3 end subroutine init_box
第三步:调整主程序调用
直接省略冗余的0值参数即可:
program main use myModule implicit none class(line_t), allocatable :: segment class(rectangle_t), allocatable :: rectangle class(box_t), allocatable :: box allocate(line_t::segment) call segment%init(12.0) call segment%print_size() allocate(rectangle_t::rectangle) call rectangle%init(12.0,5.0) call rectangle%print_size() allocate(box_t::box) call box%init(12.0,5.0,2.0) call box%print_size() end program main
运行结果
修改后代码输出与原逻辑完全一致:
Line size 12.0000000 meter Rectangle area 60.0000000 meter^2 Box volume 120.000000 meter^3
补充说明
- 该实现完全符合Fortran面向对象多态语法规则,没有破坏抽象类的接口一致性
- 可选参数的校验逻辑可按需调整,比如给线段误传多余参数时可增加警告提示
- 如果需要更灵活的构造方式,也可以为每个子类额外定义通用构造接口(generic interface),但针对当前需求,可选参数是改动最小、最直接的方案。
内容的提问来源于stack exchange,提问作者Stef1611
相关产品推荐
相关产品推荐

