了解Fortran扩展了类型和覆盖

时间:2014-08-20 17:00:49

标签: inheritance polymorphism fortran override

我试图理解Fortran 2003标准(或更高版本)中面向对象的概念。我对C ++有一些了解,所以我认为这两种语言之间有一些共同点,可以帮助我更好地理解它们。

在C ++中,多态性是通过类派生和成员函数覆盖来完成的。一个人定义了一个"摘要"几乎所有虚函数都已定义的基类。不同的派生类包含它们的实际实现。所以其他功能只需要基于"抽象"类。然后它们适用于所有派生类。

我认为在Fortran中,OOP以类似的方式完成,但存在一些差异。在我看来,需要定义一个带有一些虚函数的基类型,就像C ++一样。其他函数/子例程应遵循基类型中的成员函数定义。这是解决所有扩展类型的函数/子例程重用的方法。

我对如何编写这个想法没有更好的了解。这是我的第一次尝试:

type Basis
    integer                                 :: NBasis
contains
    private
    procedure                               :: DoNothing
    generic, public                         :: Constructor => DoNothing
    generic, public                         :: AllocateBasis => DoNothing
endtype Basis

type, extends(Basis) :: GridBasis
    private
    integer                                 :: NGrid
contains
    private
    procedure                               :: ConstructorGrid1
    procedure                               :: ConstructorGrid2
    generic, public                         :: Constructor => ConstructorGrid1, ConstructorGrid2, ConstructorGrid3
    procedure                               :: AllocateGridReal
    procedure                               :: AllocateGridCplx
    generic, public                         :: AllocateBasis => AllocateGridReal, AllocateGridCplx
endtype GridBasis
  • 首先,我如何定义" AllocateBasis"在类型Basis中,它的工作方式类似于"虚函数"并且所有扩展类型必须定义自己的版本" AllocateBasis"?

  • 其次,我如何定义" AllocateBasis"在GridBasis类型?这里的定义包含它的真实实现。

  • 第三,我如何制作" AllocateBasis"在GridBasis类型中有一个重载函数吗?即有真实版本和复杂版本,它们都被命名为#34; AllocateBasis"使用实数或复数输入可分配数组。

  • 第四,NOPASS与PASS。据我所知,如果设置了PASS,那么就会有一个指向该对象的显式指针。但是当NOPASS设定时,就没有这样的东西了。那么PASS是简化澄清的吗?

1 个答案:

答案 0 :(得分:17)

首先对您的问题提出一些意见/答案:

  • 您可以声明类型绑定过程为deferred。然后,您必须在没有特定实现的情况下定义其签名(接口)。必须将包含deferred过程的类型声明为abstract。这些类型无法实例化。所有扩展类型都必须为给定的过程提供实现,除非它们本身是abstract

  • 为了在扩展类型中为deferred过程提供实现,您只需在扩展类型中声明该过程并为其提供实现。

  • 您无法将给定类型的公共过程转换为扩展类型中的generic。但是,您可以在基本类型中定义generic并在其派生类型中对其进行扩展。

  • 默认设置pass属性,以便过程的 first 参数为类型实例。但是,您可以指定它以使其更明确。此外,您可以使用PASS(ARGNAME)形式指定,哪个参数(ARGNAME)应该是实例。这个论点不一定是程序中的第一个。

下面是一个包含自我的示例,其中应包含您要求的所有功能:

module basis_module
  implicit none

  type, abstract :: Basis
    integer :: NBasis
  contains
    procedure(allocBasisR1Interface), deferred :: allocateBasisR1
    generic :: allocateBasis => allocateBasisR1
  end type Basis

  interface 
    ! Interface for real basis allocation
    subroutine allocBasisR1Interface(self, array)
      import
      class(Basis), intent(inout) :: self
      real, intent(in) :: array(:)
    end subroutine allocBasisR1Interface
  end interface

end module basis_module


module extension_module
  use basis_module
  implicit none

  type, extends(Basis) :: GridBasis
  contains
    ! Extending the mapping allocateBasis => allocateBasisR1 of
    ! the parent type.
    generic :: allocateBasis => allocateBasisC1
    procedure :: allocateBasisC1
    ! Implementation for the deferred procedure in Basis
    procedure :: allocateBasisR1
  end type GridBasis

contains

  subroutine allocateBasisR1(self, array)
    class(GridBasis), intent(inout) :: self
    real, intent(in) :: array(:)

    self%NBasis = size(array)
    print *, "GridBasis:allocateBasisR1"

  end subroutine allocateBasisR1


  subroutine allocateBasisC1(self, array)
    class(GridBasis), intent(inout) :: self
    complex, intent(in) :: array(:)

    self%NBasis = size(array)
    print *, "GridBasis:allocateBasisC1"

  end subroutine allocateBasisC1

end module extension_module


program test
  use extension_module
  implicit none

  type(GridBasis) :: mybasis
  real :: myRealArray(10)
  complex :: myComplexArray(5)

  call mybasis%allocateBasis(myRealArray)
  call mybasis%allocateBasis(myComplexArray)

end program test