【问题标题】:Creating interface for abstract type in Fortran 90在 Fortran 90 中为抽象类型创建接口
【发布时间】:2014-09-05 10:01:45
【问题描述】:

我在 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”的实际参数必须具有相同的声明类型

有什么想法吗? 提前谢谢你

【问题讨论】:

  • 您的type1 定义似乎不相关。你是不是想写点别的?
  • 只是我正在定义的类型,我希望使用函数 initialize_ 进行初始化...我稍微更改了代码,使其更加明确。感谢您的评论!
  • 哦,我想我明白了,尽管我仍然不清楚你在做什么。编译器应该如何消除 initialize_logicinitialize_abstract 的歧义?如果logic 扩展abstract,那么调用initialize(element,element_something) 可以同时表示initialize_logicinitialize_abstract,因为element_something 既是type(logic) 又是class(abstract)。一定会发生这种情况。
  • 准确地说,您不是在 Fortran 90 中编码。类型绑定过程,例如您的 initialize_abstract,是在 2003 年标准中引入的。与 abstract 类型一样,尽管您经常使用 abstract 这个词,但您的代码并未使用它们。
  • 这篇文章 -- ibm.com/developerworks/community/blogs/… -- 比我现在有时间更好地解释了(可能比我能力更好)如何为用户定义的类型创建构造函数。这个——pgroup.com/lit/articles/insider/v3n1a3.htm——也不错。

标签: generics interface fortran abstract fortran90


【解决方案1】:

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

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

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

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

方法一(选择类型):

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    

【讨论】:

  • 感谢您的回答,问题是您的类型“抽象”应该这样声明,即:type,abstract :: abstract integer :: x contains end type abstract 在这种情况下,第一个解决方案不起作用,对于第二个,我也不认为它会起作用,但我会试一试
  • 因为你的抽象类型不是抽象的
  • @lasofivec 好的,我明白了。你不明白abstract 类是如何工作的。你不能实例化一个不可能的抽象类。因此你不能做你想做的事。做到这一点的方法要么不使abstract成为抽象类(即方法1),要么使用方法2。
  • 我不是在尝试实例化一个抽象类,我的问题比我描述的更复杂(type1 实际上也是一个抽象类型)并且肯定比你的测试用例更复杂。我会尝试写一个,以便更清楚。但是无论如何感谢您的回答:)
  • @lasofivec 好吧,我已经在周五问你澄清你在做什么。即使现在问题type1 也不是抽象的(甚至不清楚abstract 是抽象的)。我回答了我可以看到的问题,并且我相信我给出了两种有效的方法。听到它对你不起作用我很难过,但如果你做的不是你所说的,那就不足为奇了。我想知道当时怎么会有人回答这样的问题。
猜你喜欢
  • 1970-01-01
  • 2015-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-20
  • 1970-01-01
  • 2010-11-08
  • 2023-03-08
相关资源
最近更新 更多