问题描述
我仍然用"面向对象"的风格来环绕Fortran.
I am still wrapping my head around Fortran with an "object oriented" flavor.
是否可以将变量初始化为派生类型,如果我希望该变量为parameter
怎么办?
Is it possible to initialize a variable in a derived type, and what if I'd like that variable to be a parameter
?
例如,经典的animal
,cat
,bee
类型集应设置每只动物的腿数:
For example, a classic animal
, cat
, bee
set of types that should set the number of legs of each animal:
动物模块
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
,但是我的编译器(英特尔)抱怨该关键字存在语法错误.
I've found online the keyword initial
, but my compiler (Intel) complains about the keyword with a syntax error.
我尝试了自定义构造函数,但显然我无法为派生类型写一个.这是我的尝试,仅对 cat 类型:
I've tried a custom constructor but apparently I am unable to write one for derived types. This is my attempt, only on the cat type:
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
.
As the animal
type has integer, public :: nlegs = -1
, I expected the cat
to have -4
legs, but alas, it's still -1
.
推荐答案
不可能命名常量.同样,不可能声明一个抽象类型的组件,然后在扩展类型中为其值定义默认的初始化.尝试使用默认初始化重新声明该组件会导致出现问题.
It is not possible for a component to be a named constant. Also, it isn't possible to declare a component of an abstract type and then define default initialization for its value in an extending type. Attempting to redeclare the component with default initialization leads to the error of the question.
High Performance Mark的评论提供了一条途径:每个扩展类型的自定义构造函数.您可以进一步将组件设置为私有,以进行封装或保护.
High Performance Mark's comment offers one route: provide a custom constructor for each extending type setting the value appropriately. You can further set the component to private for encapsulation or protection.
或者,您可以提供一个"getter"类型绑定过程,该过程引用一个命名常量:
Alternatively, you can provide a "getter" type-bound procedure which references a named constant:
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 (并且会有类似的问题).
Finally, initial
is not standard Fortran (and would have similar problems).
这篇关于初始化派生类型中的参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!