如何避免为子模块中实现的延迟类型绑定过程重复编写相同接口
解答
完全可以避免编写第二个完整接口,有两种常用的实现方案:
方案1:复用父类抽象接口(保留submodule拆分)
利用Fortran 2008标准支持的类型绑定过程重写的参数协变特性,直接复用父类已经定义的sub_int抽象接口,不需要重复编写完整的接口定义。
调整后的模块代码如下:
MODULE m TYPE, ABSTRACT:: foo CONTAINS PROCEDURE(sub_int), DEFERRED:: sub END TYPE ABSTRACT INTERFACE SUBROUTINE sub_int(THIS, x) IMPORT:: foo CLASS(foo), INTENT(IN):: THIS DOUBLE PRECISION, INTENT(INOUT):: x END SUBROUTINE END INTERFACE TYPE, EXTENDS(foo):: foo2 CONTAINS ! 直接复用父类抽象接口声明,编译器会自动校验重写参数的协变合法性 PROCEDURE(sub_int) :: sub END TYPE END MODULE SUBMODULE (m) s CONTAINS MODULE PROCEDURE sub ! 只需要把THIS的类型改为foo2,其他参数完全和抽象接口一致即可 CLASS(foo2), INTENT(IN) :: THIS DOUBLE PRECISION, INTENT(INOUT) :: x x = x**2 END PROCEDURE END SUBMODULE
这个方案的好处是既保留了submodule拆分代码的优势,又不需要重复写接口,编译器会自动对比sub的实现和sub_int接口的匹配性,只要passed参数THIS是foo的派生类、其余参数完全一致就可以编译通过。
方案2:把实现放到主模块(完全删除第二个接口)
如果你不需要用submodule拆分代码,完全可以把sub的实现直接写到主模块的CONTAINS块里,不需要额外声明任何接口:
MODULE m TYPE, ABSTRACT:: foo CONTAINS PROCEDURE(sub_int), DEFERRED:: sub END TYPE ABSTRACT INTERFACE SUBROUTINE sub_int(THIS, x) IMPORT:: foo CLASS(foo), INTENT(IN):: THIS DOUBLE PRECISION, INTENT(INOUT):: x END SUBROUTINE END INTERFACE TYPE, EXTENDS(foo):: foo2 CONTAINS PROCEDURE(sub_int) :: sub END TYPE CONTAINS SUBROUTINE sub(THIS, x) CLASS(foo2), INTENT(IN) :: THIS DOUBLE PRECISION, INTENT(INOUT) :: x x = x**2 END SUBROUTINE END MODULE
这种方式代码最简洁,适合过程逻辑比较简单、不需要拆分文件的场景。
注意事项
- 上述两种方案都要求
sub除了passed参数THIS的类型可以变为派生类foo2之外,其余所有参数的类型、顺序、intent属性都必须和父类的抽象接口sub_int完全一致,这是Fortran类型绑定过程重写的强制要求。 - 目前主流编译器(GCC Fortran 10+、Intel Fortran 2020+、NVIDIA HPC SDK Fortran等)都完整支持上述特性,不需要额外开启编译选项。
内容的提问来源于stack exchange,提问作者Frank
相关产品推荐
相关产品推荐

