在Fortran 90中为抽象类型创建接口

时间:2014-09-05 10:01:46

标签: generics interface fortran abstract fortran90

我在Fortran90中编码,即使我知道应该避免使用抽象类型。 现在我希望定义一个可以在参数中采用抽象类型或派生类型的函数。为此,我想创建两个函数的接口,但是我收到以下错误:

  

模糊接口'initialize_abstract'和   通用接口中的'initialize_logic'   '初始化'在(1)

代码如下所示:

type type1
contains
procedure, pass(transf) :: initialize_logic
procedure, pass(transf) :: initialize_abstract
end type

interface initialize
     module procedure initialize_logic
     module procedure initialize_abstract
end interface

function initialize_logic(element, element_logic)
   type(type1), pointer :: element
   type(type_logic), pointer :: element_logic
end function

function initialize_abstract(element, element_abstract)
    type(type1), pointer :: element
    class(type_abstract), pointer :: element_abstract
end function

type_abstract从type_logic扩展。

我不知道如何摆脱这个消息错误,我真的需要能够用抽象类型或扩展类型(例如:“logic_type”)来调用它,例如:

class(type_abstract), pointer :: element_abstract
type(type_logic),     pointer :: element_logic
type(type1)                   :: e1, e2
call e1%initialize(element_abstract)
call e2%initialize(element_logic)

如果我只有一个初始化程序,接受抽象类的参数,在使用扩展类型初始化时会出现以下错误:

  

错误:(1)处'element_abstract'的实际参数必须具有相同的声明类型

有什么想法吗? 提前谢谢

1 个答案:

答案 0 :(得分:4)

编辑:完全重做,添加了抽象类方法。

有两种方法可以做到这一点。一个使用select type构造在运行时确定element的动态类型以调用正确的初始化过程。

另一种方法使用抽象类来声明延迟过程initialize_t1,这将由每个子类以不同方式实现。请注意两件事,首先我调用了一个派生类型abstract以保持您的命名约定,但它是相当混乱而不是一个好的做法。然后,真正抽象的类被称为veryAbstract,以提示其目的,并保持您的命名约定。另一点需要注意的是initialize_from_...过程绑定到veryAbstract子类而不是type1类。这可能会让人感到困惑,但这是让你能够实现目标的技巧。

两种方式均使用ifort 14进行测试。

方法1(选择类型):

module test2

type abstract 
        integer :: x
      contains
end type abstract

type, extends(abstract) :: logic 
        integer :: y
      contains
end type logic

type type1
        integer :: x
      contains
              procedure :: initialize => initialize_type1
              procedure :: initialize_abstract
              procedure :: initialize_logic
end type type1

      contains

subroutine initialize_abstract(this,element)
              class(type1),    intent(inout) :: this
              class(abstract), intent(in)    :: element
              this%x = element%x
end subroutine initialize_abstract 

subroutine initialize_logic(this,element)
              class(type1), intent(inout) :: this
              class(logic), intent(in)     :: element
              this%x = element%y
end subroutine initialize_logic 

subroutine initialize_type1(this,element)
        class(type1),    intent(inout) :: this
        class(abstract), intent(in)    :: element

        select type (element)
           type is (abstract)
                   call this%initialize_abstract(element)
           type is (logic)
                   call this%initialize_logic(element)
           class default
                   print*,"ERROR: Unknown type of the 'element' argument in 'initialize_type1'."
                   stop
        end select
end subroutine initialize_type1 
end module test2

方法2(抽象类):

module test3
type type1
        integer :: x
      contains
              procedure :: initialize => initialize_type1
end type type1

type, abstract :: veryAbstract
        contains
                procedure(init_t1), deferred :: initialize_t1
end type veryAbstract

abstract interface
   subroutine init_t1(this,t1)
           import veryAbstract
           import type1
           class(veryAbstract), intent(in)    :: this
           class(type1),        intent(inout) :: t1
   end subroutine
end interface

type, extends(veryAbstract) :: abstract 
        integer :: x
      contains
              procedure :: initialize_t1 => initialize_type1_from_abstract
end type abstract

type, extends(abstract) :: logic 
        integer :: y
      contains
              procedure :: initialize_t1 => initialize_type1_from_logic
end type logic

      contains

subroutine initialize_type1(this,element)
        class(type1),    intent(inout) :: this
        class(abstract), intent(in)    :: element
        call element%initialize_t1(this)
end subroutine initialize_type1     

subroutine initialize_type1_from_abstract(this,t1)
              class(abstract), intent(in)    :: this
              class(type1),    intent(inout) :: t1
              t1%x = this%x
end subroutine initialize_type1_from_abstract 

subroutine initialize_type1_from_logic(this,t1)
              class(logic), intent(in)    :: this
              class(type1), intent(inout) :: t1
              t1%x = this%y
end subroutine initialize_type1_from_logic 

end module test3

测试程序:

PROGRAM test 
    use test2
    !use test3

    type(abstract) :: a1
    type(logic)    :: l1
    type(type1)    :: t1
    type(type1)    :: t2

    a1%x = 1
    l1%x = 2
    l1%y = 7
    call t1%initialize(a1)
    call t2%initialize(l1)

    print*,'t1%x: ',t1%x
    print*,'t2%x: ',t2%x
end