【问题标题】:run-time polymorphism in fortran 2003fortran 2003 中的运行时多态性
【发布时间】:2013-02-22 06:23:30
【问题描述】:

我在 Fortran 2003 中编写了一些代码,这些代码使用稀疏矩阵处理大量线性代数。我正在尝试利用新标准的一些更抽象的特性,这样我的程序就更简单了,没有太多重复的代码。

我有一个过程solver,它接受一个矩阵、一些向量、所使用的迭代方法的容差等。我将一个指向名为matvec 的过程的指针传递给它; matvec 是我们用于矩阵向量乘法的子程序。

问题是,有时matvec 是一个过程,它接收额外的参数colorlist, color1, color2,高于通常发送到此过程的参数。我可以想出几种方法来解决这个问题。

第一个想法:定义两个不同的抽象接口matvec1matvec2和两个不同的求解器。这可行,但这意味着复制一些代码,这正是我试图避免的。

另一个想法:保持相同的抽象接口matvec,并使额外的参数colorlistcolor1color2可选。这意味着使它们在每个 matvec 例程中都是可选的——即使是那些它们并不是真正可选的,以及它们甚至根本不使用的例程。如果我这样做,我肯定会下地狱的。

我能想到很多其他不太理想的解决方案。我想对此提出一些意见 - 我确信有一些优雅的方法可以做到这一点,我只是不确定它是什么。

【问题讨论】:

    标签: oop polymorphism fortran


    【解决方案1】:

    问题实际上是,是否必须在每次调用过程时都传递附加参数(因为它们在两次调用之间发生变化),或者它们可以在某个时候初始化,然后在函数中使用。在后一种情况下,您可以创建一个具有抽象接口的类,该接口使用基本参数定义您的子例程matvec。然后,您可以使用更专业的类扩展该类,这些类可以包含所需的其他选项。他们仍然必须定义与父类相同的matvec 接口(具有相同的参数列表),但是当调用matvec 过程时,他们可以使用存储在其中的附加值。

    您可以找到类似案例的详细示例 in this answer(查找显示 module rechercheRacine 的第二个示例)。

    【讨论】:

      【解决方案2】:

      您可以将各种matvec 例程放在通用接口后面,而不是将过程指针作为显式参数传递:

      interface matvec
        module procedure matvec1, matvec2
      end interface
      

      然后您的solver 例程可以只使用带有或不带有额外参数的通用名称。当然,在使用 Bálint 建议的将solver 定义为具有类型绑定过程的派生类型的方法时,也可以采用相同的方法:

      type :: solver
        real, allocatable :: matrix(:,:), v1(:), v2(:)
      contains
        procedure, pass :: matvec1
        procedure, pass :: matvec2
        generic :: matvec => matvec1, matvec2
      end type
      

      主要区别在于它不使用多态性来确定要调用的正确过程,而是使用虚拟参数的特性。

      我不确定您对过程指针的意图;如果您希望在运行时更改其目标(或者可能为其“未定义”状态分配一些特殊含义),那么指针是唯一的方法,并且所有目标都需要匹配相同的抽象接口。相反,如果您只需要根据它们的参数选择几个过程之一,那么您可以利用接口(我的示例)或重载(Bálint 的示例)。类型的每个扩展都可以使用新过程扩展继承的 generic 绑定,或重载继承的特定绑定。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-04-24
        • 2015-09-22
        • 2014-01-19
        • 2011-01-10
        • 1970-01-01
        • 2015-02-21
        • 1970-01-01
        • 2016-02-03
        相关资源
        最近更新 更多