Fortran 派生类型可以包含来自不同模块的组件吗?
Can a Fortran derived type have components from different modules?
我正在开发派生类型。它不断增长,并使它所在的模块变得笨拙。有没有办法将模块分解成多个模块,并让派生类型从各个模块获取其组件?
正如@francescalus 指出的那样,您可以使用其他模块的派生类型来
创建新的派生类型。我觉得他的例子有点短,所以我写了一个
我希望这个小例子能让你了解这样的事情是如何发生的
可以工作。也许这个例子比绝对必要的要长,但我
玩得开心。
我的派生类型描述了旅行计划,包括行李和行程。
它带有一个子程序,可以打印给定的旅行计划。
module travel
use Luggage
use Routing
type tTravel
type(tItinerary) :: trip
type(tSuitcase) :: suitcase
end type tTravel
contains
subroutine printTravel(travel)
implicit none
type(tTravel), intent(in) :: travel
print '(a)',' Luggage:'
call printSuitcase(travel%suitcase)
print '(a)',' Itinerary:'
call printItinerary(travel%trip)
end subroutine printTravel
end module travel
旅行计划的两个组成部分,行李和行程,各有各的
模块。首先,行李模块:
module Luggage
type tSuitcase
integer :: socks = 2
integer :: shirts = 1
integer :: underwear = 1
integer :: raincoats = 0
end type tSuitcase
contains
subroutine printSuitcase(suitcase)
implicit none
type(tSuitcase), intent(in) :: suitcase
print '(i10,a)', suitcase%socks,' socks'
print '(i10,a)', suitcase%shirts,' shirts'
print '(i10,a)', suitcase%underwear,' underwear'
print '(i10,a)', suitcase%raincoats,' raincoats'
end subroutine printSuitcase
end module Luggage
接下来是行程模块:
module Routing
integer, parameter :: &
HOME=1, MONACO=2, IBIZA=3, BIARRITZ=4, &
nDESTINATIONS=4
character(len=8), parameter :: destination_names(nDESTINATIONS) = (/ &
'Home ', 'Monaco ', 'Ibiza ', 'Biarritz' /)
integer, parameter :: maxTripLen = 100
type tItinerary
integer :: length = 0
integer :: destinations(maxTripLen)
end type tItinerary
contains
subroutine addDestination(trip,destination)
implicit none
type(tItinerary), intent(inout) :: trip
integer, intent(in) :: destination
if (destination<1 .or. destination>nDESTINATIONS) &
stop('illegal destination')
if (trip%length >= maxTripLen) stop('Trip too long')
trip%length = trip%length + 1
trip%destinations(trip%length) = destination
end subroutine AddDestination
subroutine printItinerary(trip)
implicit none
type(tItinerary), intent(in) :: trip
integer :: i
if (trip%length==0) then
print '(a)',' Empty itinerary'
else
print '(100(a))',' '//trim(destination_names(trip%destinations(1))), &
('-',trim(destination_names(trip%destinations(i))), i=2,trip%length)
end if
end subroutine printItinerary
end module Routing
现在我只需要一个主程序:
program nestedModule
use travel
implicit none
type(tTravel) :: plans
print '(a)','Before planning anything:'
call printTravel(plans)
print *
print '(a)','Planning a trip ... hold on'
print *
call addDestination(plans%trip,HOME)
call addDestination(plans%trip,IBIZA)
call addDestination(plans%trip,BIARRITZ)
call addDestination(plans%trip,HOME)
print '(a)','Now my plans are:'
Call printTravel(plans)
end program nestedModule
正如我在第一条评论中指出的那样,在您没有回复的部分,如果您确实需要将组件作为派生类型的实际组件,而不是另一种派生类型的组件,则可以使用类型扩展, 所以如果你想避免进一步将类型构造为树。
请注意,通常使用大型平面字体不是一个好主意,但据我了解,这正是您所要求的,所以这是我的答案...
module mod1
type part1
...many components
end type
end module
module mod2
use mod1
type, extends(part1) :: part2
...many other components
end type
end module
module the_actual_type_mod
use mod2
type, extends(part2) :: the_actual_type
...many other components
end type
end module
提到的另一种方式是include
。结果不等同,但就您的目的而言几乎等同
module the_actual_type_mod
use mod2
type the_type
include "part1.f90"
include "part2.f90"
include "part3.f90"
end type
end module
我正在开发派生类型。它不断增长,并使它所在的模块变得笨拙。有没有办法将模块分解成多个模块,并让派生类型从各个模块获取其组件?
正如@francescalus 指出的那样,您可以使用其他模块的派生类型来 创建新的派生类型。我觉得他的例子有点短,所以我写了一个 我希望这个小例子能让你了解这样的事情是如何发生的 可以工作。也许这个例子比绝对必要的要长,但我 玩得开心。
我的派生类型描述了旅行计划,包括行李和行程。 它带有一个子程序,可以打印给定的旅行计划。
module travel
use Luggage
use Routing
type tTravel
type(tItinerary) :: trip
type(tSuitcase) :: suitcase
end type tTravel
contains
subroutine printTravel(travel)
implicit none
type(tTravel), intent(in) :: travel
print '(a)',' Luggage:'
call printSuitcase(travel%suitcase)
print '(a)',' Itinerary:'
call printItinerary(travel%trip)
end subroutine printTravel
end module travel
旅行计划的两个组成部分,行李和行程,各有各的 模块。首先,行李模块:
module Luggage
type tSuitcase
integer :: socks = 2
integer :: shirts = 1
integer :: underwear = 1
integer :: raincoats = 0
end type tSuitcase
contains
subroutine printSuitcase(suitcase)
implicit none
type(tSuitcase), intent(in) :: suitcase
print '(i10,a)', suitcase%socks,' socks'
print '(i10,a)', suitcase%shirts,' shirts'
print '(i10,a)', suitcase%underwear,' underwear'
print '(i10,a)', suitcase%raincoats,' raincoats'
end subroutine printSuitcase
end module Luggage
接下来是行程模块:
module Routing
integer, parameter :: &
HOME=1, MONACO=2, IBIZA=3, BIARRITZ=4, &
nDESTINATIONS=4
character(len=8), parameter :: destination_names(nDESTINATIONS) = (/ &
'Home ', 'Monaco ', 'Ibiza ', 'Biarritz' /)
integer, parameter :: maxTripLen = 100
type tItinerary
integer :: length = 0
integer :: destinations(maxTripLen)
end type tItinerary
contains
subroutine addDestination(trip,destination)
implicit none
type(tItinerary), intent(inout) :: trip
integer, intent(in) :: destination
if (destination<1 .or. destination>nDESTINATIONS) &
stop('illegal destination')
if (trip%length >= maxTripLen) stop('Trip too long')
trip%length = trip%length + 1
trip%destinations(trip%length) = destination
end subroutine AddDestination
subroutine printItinerary(trip)
implicit none
type(tItinerary), intent(in) :: trip
integer :: i
if (trip%length==0) then
print '(a)',' Empty itinerary'
else
print '(100(a))',' '//trim(destination_names(trip%destinations(1))), &
('-',trim(destination_names(trip%destinations(i))), i=2,trip%length)
end if
end subroutine printItinerary
end module Routing
现在我只需要一个主程序:
program nestedModule
use travel
implicit none
type(tTravel) :: plans
print '(a)','Before planning anything:'
call printTravel(plans)
print *
print '(a)','Planning a trip ... hold on'
print *
call addDestination(plans%trip,HOME)
call addDestination(plans%trip,IBIZA)
call addDestination(plans%trip,BIARRITZ)
call addDestination(plans%trip,HOME)
print '(a)','Now my plans are:'
Call printTravel(plans)
end program nestedModule
正如我在第一条评论中指出的那样,在您没有回复的部分,如果您确实需要将组件作为派生类型的实际组件,而不是另一种派生类型的组件,则可以使用类型扩展, 所以如果你想避免进一步将类型构造为树。
请注意,通常使用大型平面字体不是一个好主意,但据我了解,这正是您所要求的,所以这是我的答案...
module mod1
type part1
...many components
end type
end module
module mod2
use mod1
type, extends(part1) :: part2
...many other components
end type
end module
module the_actual_type_mod
use mod2
type, extends(part2) :: the_actual_type
...many other components
end type
end module
提到的另一种方式是include
。结果不等同,但就您的目的而言几乎等同
module the_actual_type_mod
use mod2
type the_type
include "part1.f90"
include "part2.f90"
include "part3.f90"
end type
end module