如何根据多态变量的数据类型指定要执行的过程

时间:2013-09-24 12:33:09

标签: oop polymorphism fortran fortran2003

请考虑以下示例代码:

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,以便根据参数的动态类型自动选择一个过程?

我想避免使用长序列"选择类"。

欢迎任何重写代码的建议!

2 个答案:

答案 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)内部的动态类型。好处是双重的:

  1. calcul可以独立于其他参数测试每个参数的类型。如果是这种情况,您仍然需要编写三个calcul构造,但它们不会嵌套或重复。

  2. 您可以使用单一调度(使用类型绑定过程)来完全删除对select type构造的需求。

  3. 我很难想到这个问题中的代码确实是您可以使用的最佳设计的情况。

    如果select type确实为每个动态类型做了一些完全“不同”的事情,以与调用它的代码相关的方式,则调用代码不应该使用多态指针(例如,应该有每个不同的calcul都有不同的complexType

    但是如果calcul的每个版本基本上都在进行“相同”的操作(就高级代码所知/关心而言),无论动态类型如何,那么应该只有一个版本,它应该接受属于基类的参数。