Инициализировать параметр в производном типе - PullRequest
0 голосов
/ 29 октября 2019

Я все еще оборачиваюсь вокруг Фортрана с " объектно-ориентированным " ароматом.

Можно ли инициализировать переменную в производном типе , и что если я бы хотел, чтобы эта переменная была parameter?

Например, классический animal, cat, bee набор типов, которые должны определять количество ног каждого животного:

модуль животного

module animal_module
    implicit none

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

модуль cat

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, но мой компилятор (Intel) жалуется на ключевое слово с синтаксисомошибка.

Приложение

Я пробовал пользовательский конструктор , но, очевидно, я не могу написать его для производных типов. Это моя попытка, только для типа 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.

1 Ответ

1 голос
/ 30 октября 2019

невозможно для компонента быть именованной константой. Кроме того, невозможно объявить компонент абстрактного типа, а затем определить инициализацию по умолчанию для его значения в расширяемом типе. Попытка переопределить компонент с инициализацией по умолчанию приводит к ошибке вопроса.

Комментарий High Performance Mark предлагает один маршрут: предоставьте пользовательский конструктор для каждого расширяющего типаустановить значение соответствующим образом. Кроме того, вы можете установить для компонента значение private для инкапсуляции или защиты.

Кроме того, вы можете предоставить процедуру с привязкой к типу "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

Наконец, initial не является стандартным Fortran (и может иметь аналогичные проблемы).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...