Fortran派生类型是否可以包含来自不同模块的组件?

时间:2018-04-24 21:03:28

标签: module fortran derived-types

我正在开发派生类型。它不断增长,正在使它所处的模块变得笨拙。有没有办法将模块分解为多个模块,并使派生类型从各个模块中获取其组件?

2 个答案:

答案 0 :(得分:3)

正如@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

答案 1 :(得分:2)

正如我在第一篇评论中指出的那样,在你没有回复的部分中,如果你确实需要组件作为派生类型的实际组件,而不是另一个派生类型的组件,则可以使用类型扩展,所以如果你想避免进一步将类型结构化为树。

请注意,一般来说,拥有大型扁平型不是一个好主意,但据我所知它是你要求的,所以这里是我的答案......

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