请考虑以下示例代码:
module mod
implicit none
type :: typeBase1
integer :: A1
end type
type :: typeBase2
integer :: A3
end type
type :: typeBase3
integer :: A3
end type
type, extends(typeBase1) :: typeDerived1
! Void
end type
type, extends(typeBase2) :: typeDerived2
! Void
end type
type, extends(typeBase3) :: typeDerived3
! Void
end type
type, extends(typeBase1) :: typeDerived11
! Void
end type
type, extends(typeBase2) :: typeDerived21
! Void
end type
type, extends(typeBase3) :: typeDerived31
! Void
end type
type :: complexType
class(typeBase1), pointer :: ptrBase1 ! typeBase1, 2 and 3 are extensible
class(typeBase2), pointer :: ptrBase2
class(typeBase3), pointer :: ptrBase3
end type
interface calcul
subroutine calculA(obj1, obj2, obj3)
import
type(typeDerived1) :: obj1 ! typeDerived 1, 2 et 3 are derived type of typeBase1, 2 and 3
type(typeDerived2) :: obj2
type(typeDerived3) :: obj3
end subroutine
subroutine calculB(obj1, obj2, obj3)
import
type(typeDerived11) :: obj1 ! typeDerived 11, 21 et 31 are derived type of typeBase1, 2 and 3
type(typeDerived21) :: obj2
type(typeDerived31) :: obj3
end subroutine
end interface calcul
contains
subroutine calculComplexType(complex)
type(ComplexType), intent(inout) :: complex
call calcul(complex % ptrBase1, complex % ptrBase2, complex % ptrBase3)
end subroutine
end module mod
我想要做的是子程序calculComplexType根据ptrBase1,ptrBase2和ptrBase3的动态类型调用子程序calcul的不同版本。
代码不起作用,因为编译器使用以下接口查找子例程:
subroutine calcul(obj1, obj2, obj3)
class(typeBase1) :: obj1
class(typeBase1) :: obj2
class(typeBase1) :: obj3
end subroutine
无论动态类型的ptrBase1,ptrBase2和ptrBase3是什么。
我的问题是:在Fortran中有没有办法编写接口calcul,以便根据参数的动态类型自动选择一个过程?
我想避免使用长序列"选择类"。
欢迎任何重写代码的建议!
答案 0 :(得分:1)
如果您根据所有三个参数请求调度,则无法完成。有些语言为此提供了所谓的multimethods。
在Fortran中,您可以使用普通的单一调度方法(type-bound procedures),但在这种情况下,它只能根据一个参数选择子例程。
否则你必须使用选择select type构造并为每个可能的组合制作一个case
,无论是在一个程序中,还是在它的更多版本之间进行选择。
对于两个参数,您还可以考虑double dispatch pattern。
答案 1 :(得分:0)
这在Fortran中根本不可能;使用多态的最佳方法是使用重写的类型绑定过程,根据一个特定实体的动态类型选择一个函数。
但是,根据calcul
的性质,定义只有一个calcul
版本的多态参数(即class(typeBase1)
,{{1}更有意义。 },class(typeBase2)
),并处理class(typeBase3)
内部的动态类型。好处是双重的:
calcul
可以独立于其他参数测试每个参数的类型。如果是这种情况,您仍然需要编写三个calcul
构造,但它们不会嵌套或重复。
您可以使用单一调度(使用类型绑定过程)来完全删除对select type
构造的需求。
我很难想到这个问题中的代码确实是您可以使用的最佳设计的情况。
如果select type
确实为每个动态类型做了一些完全“不同”的事情,以与调用它的代码相关的方式,则调用代码不应该使用多态指针(例如,应该有每个不同的calcul
都有不同的complexType
。
但是如果calcul
的每个版本基本上都在进行“相同”的操作(就高级代码所知/关心而言),无论动态类型如何,那么应该只有一个版本,它应该接受属于基类的参数。