Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oop 在Fortran中扩展对象并重写过程而不延迟_Oop_Fortran_Polymorphism_Intel Fortran - Fatal编程技术网

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语句,询问我是否使用了feature
a
,然后执行一些额外的操作。 这是非常令人沮丧的,因为不同的功能似乎与其他例程非常随意地联系在一起,并且很难维护

为了避免这种情况,我决定采取以下措施:

我定义了一个对象
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(?)等