Oop fortran 2003中的运行时多态性
我正在用Fortran 2003编写一些代码,用稀疏矩阵做很多线性代数。我试图利用新标准的一些更抽象的特性,这样我就有了更简单的程序,而没有太多重复的代码 我有一个程序Oop fortran 2003中的运行时多态性,oop,polymorphism,fortran,Oop,Polymorphism,Fortran,我正在用Fortran 2003编写一些代码,用稀疏矩阵做很多线性代数。我试图利用新标准的一些更抽象的特性,这样我就有了更简单的程序,而没有太多重复的代码 我有一个程序solver,它接受一个矩阵、一些向量、所用迭代方法的容差等。我将一个指向名为matvec的程序的指针传递给它matvec是我们用于矩阵向量乘法的子例程 问题是,有时matvec是一个过程,它在发送到此过程的常规参数之上,接收额外的参数colorlist、color1、color2。我可以想出几种方法来处理这个问题 第一个想法:定
solver
,它接受一个矩阵、一些向量、所用迭代方法的容差等。我将一个指向名为matvec
的程序的指针传递给它matvec
是我们用于矩阵向量乘法的子例程
问题是,有时matvec
是一个过程,它在发送到此过程的常规参数之上,接收额外的参数colorlist、color1、color2
。我可以想出几种方法来处理这个问题
第一个想法:定义两个不同的抽象接口matvec1
,matvec2
和两个不同的解算器。这是可行的,但它意味着复制一些代码,这正是我试图避免的
另一个想法是:保持相同的抽象接口matvec
,并使额外的参数colorlist
,color1
,color2
可选。这意味着在每一个matvec例程中使它们成为可选的——即使它们不是真正可选的,或者对于它们根本不被使用的例程也是如此。如果我这样做,我肯定会下地狱
我可以想出很多其他的非最佳解决方案。我想了解一下这方面的一些信息——我确信有一种优雅的方法可以做到这一点,我只是不确定它是什么。问题是,是否每次调用过程时都必须传递额外的参数(因为它们在两次调用之间发生变化),或者可以在某个点初始化它们,然后在函数中使用它们。在后一种情况下,您可以创建一个具有抽象接口的类,该接口使用基本参数定义子例程
matvec
。然后,您可以使用更专门的类来扩展该类,这些类可以容纳所需的其他选项。它们仍然必须将相同的matvec
接口定义为父类(具有相同的参数列表),但在调用它们的matvec
过程时,它们可以使用存储在其中的附加值
您可以找到一个类似情况的详细示例(查找显示
模块RecherAcine
的第二个示例)。您可以将各种matvec
例程放在通用接口后面,而不是将过程指针作为显式参数传递:
interface matvec
module procedure matvec1, matvec2
end interface
然后,您的解算器
例程可以只使用通用名称,包括或不包括额外参数。当使用Bálint建议的方法将解算器
定义为具有类型绑定过程的派生类型时,当然也可以采用相同的方法:
type :: solver
real, allocatable :: matrix(:,:), v1(:), v2(:)
contains
procedure, pass :: matvec1
procedure, pass :: matvec2
generic :: matvec => matvec1, matvec2
end type
主要区别在于,这并不是使用多态性来确定要调用的正确过程,而是使用伪参数的特征
我不确定您对过程指针的意图;如果您希望在运行时更改其目标(或者可能为其“未定义”状态指定一些特殊含义),那么指针是唯一的方法,所有目标都需要匹配相同的抽象接口。如果您只需要根据它们的参数选择几个过程中的一个,那么您可以利用接口(我的示例)或重载(Bálint的示例)。类型的每个扩展都可以使用新过程扩展继承的泛型绑定,或者重载继承的特定绑定