Class 指针中的Fortran多态性
我尝试使用指针在对象之间创建链接。使用Fortran,代码如下:Class 指针中的Fortran多态性,class,pointers,fortran,polymorphism,Class,Pointers,Fortran,Polymorphism,我尝试使用指针在对象之间创建链接。使用Fortran,代码如下: module base_pars_module type,abstract,public :: base_pars end type end module module test_parameters_module use base_pars_module type, extends(base_pars) :: test_pars contains procedure :: w
module base_pars_module
type,abstract,public :: base_pars
end type
end module
module test_parameters_module
use base_pars_module
type, extends(base_pars) :: test_pars
contains
procedure :: whoami
end type
contains
function whoami(this) result(iostat)
class( test_pars) :: this
write(*,*) 'i am a derived type child of base_pars'
end type
end module
module base_mask_module
use base_pars module
type, abstract , public :: base_mask
class(base_pars),pointer :: parameters
end type
end module
module test_mask_module
use base_mask_module
implicit none
type, extends(base_mask) :: test_mask
end type
end module
program driver
type(test_pars) , target :: par_Test
type(test_mask) :: mask_test
iostat= par_test%whoami()
mask_test%parameters=>par_test
iostat=mask_test%parameters%whoami()
end program
base\u mask\u模块处的parameters
是带有base\u pars
类的指针。我想用这个指针来引用par\u test
对象,它是扩展base\u pars
类型的test\u pars
类型。因此指针和目标具有相同的类。但当我编译这个时,它会给出一个错误:
driver.f90:17.37:
iostat=mask_test%parameters%whoami()
1
Error: 'whoami' at (1) is not a member of the 'base_pars' structure
这是一个bug还是我做错了什么?
当你有这样的多态性时,有两件事需要考虑:一个对象的动态类型和它的声明类型。测试掩码
(基本掩码
)的参数
组件声明为
class(base_pars),pointer :: parameters
因此,这样的组件已声明类型base\u pars
接下来是指针分配
mask_test%parameters=>par_test
mask\u test%参数的动态类型与par\u test
相同:test\u pars
。但是,它是声明的类型base\u pars
,当我们关心它的组件和绑定时,声明的类型很重要base\u pars
确实没有whoami
那么,您需要一个声明了typepar\u test
的东西。在不更改派生类型定义的情况下,您可以使用select type
构造来执行此操作
select type (pars => mask_test%parameters)
class is (par_test)
iostat=pars%whoami() ! pars of declared type par_test associated with mask_test%parameters
end select
也就是说,使用这种方法很快就会变得非常乏味。始终使用选择类型
,区分众多扩展类型,将是一个相当大的难题。另一种方法是确保声明的类型base\u pars
具有绑定whoami
。我们没有如上所述更改主程序,而是更改模块base\u pars\u module
:
module base_par_modules
implicit none ! Encourage good practice
type,abstract,public :: base_pars
contains
procedure(whoami_if), deferred :: whoami
end type
interface
integer function whoami_if(this)
import base_pars ! Recall we're in a different scope from the module
class(base_pars) this
end function
end interface
end module
因此,我们在base\u pars
中有一个延迟绑定,该绑定后来被扩展类型test\u pars
中的绑定覆盖<然后,主程序中的code>mask\u test%parameters%whoami()
是有效的,调用的函数是动态类型的parameters
提供的函数
这里的两种方法都解决了所声明的参数类型的绑定问题。哪一个最适合您的实际问题取决于您的总体设计
如果您知道您的类型层次结构将与基类型有足够的共同点(即,所有类型都将提供whoami
绑定),那么使用第二种方法是有意义的。使用第一种方法,而不是当你有奇怪的特殊情况,我建议这应该是罕见的 但是,这段代码无法编译。主程序中缺少一些use
s。作为松散的指导原则(存在有效的异常),使用select type是基础类型层次结构出现问题的征兆,特别是当代码所做的一切都是调用选择器的绑定时(在这种情况下,您可以通过选择类型进行动态分派,以通过绑定调用动态分派)。这完全取决于OP试图做什么,但更合适的解决方案可能是将whoami
绑定作为延迟绑定移动到基类型中。在这个回答中,至少应该对选择类型的使用附加某种限定。谢谢。我希望已经涵盖了您的评论。经过反思,我应该ed一开始就谈到了更一般的问题。感谢@francescalus的解释,但延迟绑定在这里不是一个解决方案。我试图做的是在同一类的对象之间建立连接。函数“whoami”只是一个例子。我希望所有继承“base_mask”对象的对象都有一个类“b”的指针ase_pars.@dundaryilmaz恐怕我可能误解了您的问题,但是当您有一个声明类型为base_pars
的组件指针时(如问题中所述),则不能引用不在基本部分声明中的组件的绑定,无论其动态类型如何。如果希望测试部分声明类型测试部分
(例如)然后您必须声明它是这样的,而不是依赖于动态类型test\u pars
(除非您使用select type
构造)@francescalus我试着用类的概念来做这件事。因为base_pars和test_pars有父子关系,父类/类型的声明指针应该和子类/类型一起工作。我相信其他OO语言也是这样工作的。