Oop 在Fortran中扩展对象并重写过程而不延迟
我有一个具有许多不同特性和方法的代码。某些方法都适用于同一特征,即只能选择一个选择中的一个Oop 在Fortran中扩展对象并重写过程而不延迟,oop,fortran,polymorphism,intel-fortran,Oop,Fortran,Polymorphism,Intel Fortran,我有一个具有许多不同特性和方法的代码。某些方法都适用于同一特征,即只能选择一个选择中的一个 type,extends(t_inject) :: t_inject_a contains procedure, nopass :: inject => inject_a end type 此外,根据功能的不同,我可能需要在其他地方修改子例程。所以在例程inject的循环中,我可能会有一个小if语句,询问我是否使用了featurea,然后执行一些额外的操作。 这是非常令人沮丧的,
type,extends(t_inject) :: t_inject_a
contains
procedure, nopass :: inject => inject_a
end type
此外,根据功能的不同,我可能需要在其他地方修改子例程。所以在例程inject
的循环中,我可能会有一个小if语句,询问我是否使用了featurea
,然后执行一些额外的操作。
这是非常令人沮丧的,因为不同的功能似乎与其他例程非常随意地联系在一起,并且很难维护
为了避免这种情况,我决定采取以下措施:
我定义了一个对象tuinject
,目的是执行例程inject
。我重写了我的例程inject
,这样它就只包含所有不同场景的通用代码
type t_inject
contains
procedure,nopass :: inject => inject_default
end type
现在我有了另一个对象来处理我的功能A
,以防它被选中
type,extends(t_inject) :: t_inject_a
contains
procedure, nopass :: inject => inject_a
end type
我的子程序inject_a和inject具有相同的接口。例如
subroutine inject_a( part )
type(t_part) , intent(inout) :: part % an external data type
call inject(part)
! do the extra bit of stuff you need to do
end subroutine
subroutine inject( part)
type(t_part) , intent(inout) :: part % an external data type
! carry out the default stuff
end subroutine
现在在我的主程序中
class(t_inject) :: inj
allocate(inj :: t_inject_a)
call inj% inject ( part)
你是这样做的吗?它有效吗?我最初想用
延迟的注入过程来实现一个抽象声明的类型,这样我就可以扩展了。
但对于一个非常小的问题,我可能不需要它-我还想知道我的调用callinj%inject(part)
是否足以让编译器知道该去哪里。有时我看到一些代码在调用之前需要类是
条件 我认为有三点需要修改:
- 类型绑定的过程需要引用实际的过程名称(通过
=>
)。因此,我已将模块过程的名称inject()
更改为inject\u default()
。(但也请参见test2.f90)
- 我们需要将
allocatable
附加到一个类变量(例如,inj2
)上,以便用具体类型(例如,t\u inject\u a
)分配它
- 在
allocate
语句中,具体类型的名称应出现在:
之前,以便allocate(t\u inject\u a::inj2)
修改后的代码可能如下所示:
!! test.f90
module test_mod
implicit none
type t_inject
contains
procedure, nopass :: inject => inject_default
endtype
type, extends(t_inject) :: t_inject_a
contains
procedure, nopass :: inject => inject_a
endtype
type t_part !! some other type
integer :: x = 100, y = 200
endtype
contains
subroutine inject_default( part )
type(t_part), intent(inout) :: part
print *, "x = ", part % x
endsubroutine
subroutine inject_a( part )
type(t_part), intent(inout) :: part
call inject_default( part )
print *, "y = ", part % y
endsubroutine
end
program main
use test_mod
implicit none
class( t_inject ), allocatable :: inj1, inj2
type( t_part ) :: part
!! Polymorphic allocation with concrete types.
allocate( t_inject :: inj1 )
allocate( t_inject_a :: inj2 )
print *, "inj1:"
call inj1 % inject( part )
print *, "inj2:"
call inj2 % inject( part )
end
“gfortran-8测试90&./a.out”给出
我们还可以使用模块过程inject()
(而不是inject\u default()
),方法是使用过程nopass::inject
,例如:
!! test2.f90
module test_mod
implicit none
type t_inject
contains
procedure, nopass :: inject
! procedure, nopass :: inject => inject !! this also works
endtype
type, extends(t_inject) :: t_inject_a
contains
procedure, nopass :: inject => inject_a
endtype
type t_part !! some other type
integer :: x = 100, y = 200
endtype
contains
subroutine inject( part )
type(t_part), intent(inout) :: part
print *, "x = ", part % x
endsubroutine
subroutine inject_a( part )
type(t_part), intent(inout) :: part
call inject( part )
print *, "y = ", part % y
endsubroutine
end
!! The remaining part (and the result) is the same...
此外,还可以在不同的文件中分离实际过程,如inject()
,并使用它们来定义新类型,如tuinject
(请参见下面的mylib.f90
和test3.f90
)。这对于重用某些库文件中的例程可能很有用
!! mylib.f90
module mylib
implicit none
type t_part !! some other type
integer :: x = 100, y = 200
endtype
contains
subroutine inject( part )
type(t_part), intent(inout) :: part
print *, "x = ", part % x
end
subroutine inject_a( part )
type(t_part), intent(inout) :: part
call inject( part )
print *, "y = ", part % y
end
end
!! test3.f90
module test_mod
use mylib
implicit none
type t_inject
contains
procedure, nopass :: inject
endtype
type, extends(t_inject) :: t_inject_a
contains
procedure, nopass :: inject => inject_a
endtype
end
!! The main program is the same as test.f90.
!! compile: gfortran-8 mylib.f90 test3.f90
非常感谢你。请允许我问一下,只有在声明类型的不同文件部分中定义了“延迟”过程(已从抽象类型扩展而来)时,才可以使用带有相应延迟过程的抽象声明类型。我只是想知道后一种方法何时变得有用(我可能误解了你的问题,但无论如何…)即使实际的过程在不同的文件中给出,我们也可以通过use
语句定义一个新类型(请参阅上面更新的部分,mylib.f90和test3.f90)。但在其他情况下,延迟绑定可能也很有用……因为我猜主题相当广泛,在一些论坛(而不是像这里这样的问答网站)上发布相关问题以进行更多讨论可能很有用,比如(例如)或reddit(?)等