运行时多态性在fortran 2003中

时间:2013-03-07 06:35:12

标签: oop polymorphism fortran

我在Fortran 2003中编写了一些代码,它使用稀疏矩阵执行大量线性代数。我正在尝试利用新标准的一些更抽象的功能,所以我有更简单的程序,没有太多的重复代码。

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

问题是,有时候matvec是一个过程,它会在发送到此过程的常规参数之上引入额外的参数colorlist, color1, color2。我可以想到几种解决这个问题的方法。

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

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

我可以想到许多其他不太理想的解决方案。我想对此有所了解 - 我确信有一些优雅的方法可以做到,我只是不确定它是什么。

2 个答案:

答案 0 :(得分:5)

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

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

答案 1 :(得分: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绑定,或者重载继承的特定绑定。