了解Fortran扩展类型和覆盖 [英] Understanding Fortran extends types and override

查看:140
本文介绍了了解Fortran扩展类型和覆盖的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to understand the object-oriented concepts in Fortran 2003 standards (or later). I have some knowledge in C++ so I think there are some common ideas between these two languages which can help me understand them better.

在C ++中,通过类派生和成员函数重写实现多态.定义了一个抽象"基类,其中定义了几乎所有的虚函数.不同的派生类包含它们的实际实现.因此,其他功能只需要基于抽象"类进行编程即可.然后它们适用于所有派生类.

In C++, the polymorphism is done through class derivation and member function overriding. One defines a "abstract" base class where almost all the virtual functions are defined. Different derived classes contains the actual implementation of them. So other functions just need to program based on the "abstract" class. Then they works for all derived classes.

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

I think in Fortran, the OOP is done in a similar way but there are some differences. In my opinion, it is needed to define a base type with some virtual functions just like C++. And other functions/subroutines should follow the member function definition in the base type. That's the way of resolving the reuse of the function/subroutines for all extends types.

我对如何进行编程没有更好的主意.这是我的第一次尝试:

I don't have a better idea on how to program the idea. Here is my first attempt:

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

  • 首先,如何定义Basis类型的"AllocateBasis",使其像虚函数"一样工作,并且所有扩展类型都必须定义自己的"AllocateBasis"版本?

    • First, how can I define the "AllocateBasis" in type Basis such that it works like the "virtual function" and all extended types must define their own version of "AllocateBasis"?

      第二,如何在GridBasis类型中定义"AllocateBasis"?这里的定义包含了它的实际实现.

      Second, how can I define "AllocateBasis" in type GridBasis? The definition here contains the real implementation of it.

      第三,如何使GridBasis类型的"AllocateBasis"成为重载函数?即存在真实版本和复杂版本,它们都被命名为"AllocateBasis",具有真实或复杂的输入可分配数组.

      Third, how can I make "AllocateBasis" in type GridBasis a overload function? i.e. there are real version and complex version and both of them are named "AllocateBasis" with real or complex input allocatable arrays.

      第四,NOPASS vs PASS.据我了解,如果设置了PASS,则存在指向该对象的显式指针.但是,当设置了NOPASS时,就没有这种事情了.因此,PASS简化了说明?

      Fourth, NOPASS vs PASS. As I understand, if PASS is set then there is a explicit pointer to the object. But when NOPASS is set, there is no such a thing. So PASS is simplify for clarification?

      推荐答案

      首先对您的问题发表评论/答案:

      First some comments/answers to your questions:

      • 您可以将类型绑定过程声明为deferred.然后,您仅需定义其签名(接口)即可,而无需特定的实现.包含deferred过程的类型必须声明为abstract.此类不能被实例化.所有扩展类型都必须提供给定过程的实现,除非它们本身是abstract.

      • You can declare a type bound procedure being deferred. Then you have to define its signature (interface) only without a specific implementation. The type containing the deferred procedure must be declared abstract. Such types can not be instantiated. All extending types must provide an implementation for the given procedure, unless they are themselves abstract.

      为了以扩展类型提供deferred过程的实现,您只需以扩展类型声明该过程并为其提供实现.

      In order to provide an implementation for a deferred procedure in an extending type, you just declare the procedure in the extending type and provide an implementation for it.

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

      You can not turn a public procedure of a given type into a generic in an extending type. You can, however, define a generic already in the base type and extend it in its derived types.

      默认情况下设置了pass属性,因此该过程的 first 参数将是类型实例.但是,您可以指定它以使其更加明确.此外,您可以以PASS(ARGNAME)的形式使用它来指定哪个参数(ARGNAME)应该是实例.此参数不必是过程中的第一个参数.

      The pass attribute is set by default, so that the first argument of the procedure will be the type instance. You can, however, specify it to make it more explicit. Additionally, you could use it in the form PASS(ARGNAME) to specify, which argument (ARGNAME) should be the instance. This argument needs not be the first one in the procedure.

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

      Below you find a self containing example, which should contain all the features you asked for:

      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
      

      这篇关于了解Fortran扩展类型和覆盖的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆