我搞砸了我以前的问题,不得不删除它。这是一个新的:
我从this quite helpful site中获得了大部分代码:
module shape_mod
type shape
integer :: color
logical :: filled
integer :: x
integer :: y
contains
procedure :: initialize
end type shape
type, extends(shape) :: rectangle
integer :: length
integer :: width
end type rectangle
type, extends(rectangle) :: square
end type square
interface
subroutine initialize(sh, color, filled, x, y, length, width)
import shape
class(shape) :: sh
integer :: color
logical :: filled
integer :: x
integer :: y
integer, optional :: length
integer, optional :: width
end subroutine
end interface
end module
subroutine initialize(sh, color, filled, x, y, length, width)
! initialize shape objects
class(shape) :: sh
integer :: color
logical :: filled
integer :: x
integer :: y
integer, optional :: length
integer, optional :: width
! do stuff with shape
end subroutine initialize
program drv
use shape_mod
type(shape) :: sh
call sh%initialize(1, .true., 0, 0, 5, 10)
end program
这无法编译(如我的上一个问题的答复者所指出的那样),并显示以下错误:
gfortran shape2.f90
shape2.f90:38:16:
class(shape) :: sh
1
Error: Derived type ‘shape’ at (1) is being used before it is defined
shape2.f90:46:7: Error: Symbol ‘sh’ at (1) has no IMPLICIT type
shape2.f90:47:7: Error: Symbol ‘sh’ at (1) has no IMPLICIT type
shape2.f90:48:7: Error: Symbol ‘sh’ at (1) has no IMPLICIT type
shape2.f90:49:7: Error: Symbol ‘sh’ at (1) has no IMPLICIT type
所以,我的问题是,我该怎么做才能使subroutine initialize()
了解type shape
?我唯一能想到的就是在其中放入use语句:
subroutine initialize(sh, color, filled, x, y, length, width)
use shape_mod
! initialize shape objects
class(shape) :: sh
integer :: color
logical :: filled
...
end subroutine initialize
但这给了我一个新的错误:
gfortran shape2.f90
shape2.f90:37:8:
use shape_mod
1
Error: ‘initialize’ of module ‘shape_mod’, imported at (1), is also the name of the current program unit
如何编写子例程是我上面引用的链接所不具备的一件事。有没有办法做到这一点?还是initialiaze()
必须是shape_mod的一部分才能起作用?
答案 0 :(得分:2)
在模块中,您为外部过程initialize
定义了一个接口。在子例程定义中使用此模块时,您可以访问子例程本身的接口。
您不能这样做。
幸运的是,您可以避免让该接口访问
use shape_mod, only shape
现在,由于在类型绑定中使用外部过程进行了设计,因此上述操作是必需的。通常,人们希望不要以这种方式使用外部过程。如我们所见,使用外部过程会带来额外的复杂性,既要使用定义类型的模块,又必须手动指定过程的接口。
有时候外部接口会很有用,但是这里导致问题的示例的目的也许是教学上的,而不是简单的。这里没有明显的原因为什么initialize
不应该是模块过程。
相反,请考虑示例
interface
subroutine ext()
end subroutine
end interface
type mytype
contains
procedure(iface), nopass :: ext
end type
外部子例程ext
没有传递对象的虚拟对象(绑定具有nopass
),因此不需要在其中定义mytype
的模块。这是一个简化。
最后,正如高性能标记所注释的那样,也许initialize
甚至不必成为绑定名称。而是可以使用“构造函数”:
type mytype
end mytype
interface mytype
procedure intialize_mytype
end interface
留下详细信息供感兴趣的读者从其他来源中查找。