【问题标题】:Initialize a parameter in a derived type初始化派生类型中的参数
【发布时间】:2019-10-29 17:14:38
【问题描述】:

我仍然用“面向对象”的风格来围绕 Fortran。

是否可以在派生类型中初始化变量,如果我希望该变量为parameter,该怎么办?

例如,经典的animalcatbee 类型集应该设置每只动物的腿数:

动物模块

module animal_module
    implicit none

    type, abstract :: animal
        private
        integer, public :: nlegs = -1
    contains
...

猫模块

module cat_module
    use animal_module, only : animal
    implicit none

    type, extends(animal) :: cat
        private
        ! error here about redefining nlegs...
        integer, public :: nlegs = 4
...

我在网上找到了关键字initial,但我的编译器(英特尔)抱怨该关键字存在语法错误。

附录

我尝试了custom constructor,但显然我无法为派生类型编写一个。这是我的尝试,只针对 cat 类型:

module cat_module
    use animal_module, only : animal
    implicit none

    type, extends(animal) :: cat
        private
        real :: hidden = 23.
    contains
        procedure :: setlegs => setlegs
        procedure :: speak
    end type cat

    interface cat
        module procedure init_cat
    end interface cat

contains

    type(cat) function init_cat(this)
        class(cat), intent(inout) :: this
        this%nlegs = -4
    end function init_cat
...

program oo
    use animal_module
    use cat_module
    use bee_module
    implicit none

    character(len = 3) :: what = "cat"
    class(animal), allocatable :: q

    select case(what)
    case("cat")
        print *, "you will see a cat"
        allocate(cat :: q)
...
    print *, "this animal has ", q%legs(), " legs."

由于animal 类型有integer, public :: nlegs = -1,我希望cat-4 腿,但唉,它仍然是-1

【问题讨论】:

  • 问题是,cat 已经有一个名为nlegs 的成员变量,因为它是animal 的扩展。所以编译器不会让你声明另一个同名成员。我认为您将不得不破解将nlegs for cats 设置为4 的构造函数。
  • 您是想拥有该派生类型的(命名)常量,还是让对象中的组件成为常量?
  • 我正在尝试为所有扩展动物的类型提供一个通用字段,在本例中为腿数。
  • @HighPerformanceMark 我同意,虽然我不太了解它们是如何工作的。
  • 除了对它们的显式引用之外,不会调用构造函数:没有“分配时的自动构造”。

标签: oop fortran


【解决方案1】:

not possible 让组件成为命名常量。此外,不可能声明一个抽象类型的组件,然后在扩展类型中为其值定义默认初始化。尝试使用默认初始化重新声明组件会导致问题的错误。

高性能标记的comment 提供了一种途径:为每个扩展类型提供一个custom constructor,并适当地设置值。您可以进一步将组件设置为私有以进行封装或保护。

或者,您可以提供一个引用命名常量的“getter”类型绑定过程:

module animal_module
  implicit none

  type, abstract :: animal
   contains
     procedure(getter), deferred :: nlegs
  end type animal

  abstract interface
     integer function getter(creature)
       import animal
       class(animal) creature
     end function getter
  end interface

end module animal_module

module cat_module
  use animal_module, only : animal
  implicit none

  type, extends(animal) :: cat
   contains
     procedure :: nlegs => nlegs_cat
  end type cat

contains

  integer function  nlegs_cat(creature)
    class(cat) creature
    integer, parameter :: my_cat_has_legs=3
    nlegs_cat = my_cat_has_legs
  end function nlegs_cat

end module cat_module

  use cat_module
  implicit none

  class(animal), allocatable :: fido

  fido = cat()
  print*, "Fido has", fido%nlegs(), "legs"
end

最后,initialnot standard Fortran(并且会有类似的问题)。

【讨论】:

  • 我已经尝试过自定义构造方法,因为它似乎是最完美的一种,但显然我在理解构造函数在 fortran 中的工作方式方面遗漏了一些东西。
  • 显示您的构造函数尝试的另一个问题可能是解决此问题的最清晰方法。您可以在此处链接到您的问题(提及收到的 cmets)以获取上下文。
  • 我有你建议的posted a question
猜你喜欢
  • 1970-01-01
  • 2017-12-13
  • 1970-01-01
  • 2020-08-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-10
相关资源
最近更新 更多