- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Is it possible to encapsulate the data contained in a derived type? Assume I defined a derived type MY_TYPE which contains a number of variables. I do not want the user of my libraries to have direct access to the internal content of structures of type MY_TYPE. Instead, they should only access this data through dedicated subroutines associated to MY_TYPE.
It doesn't seem possible to do this so far. Is there a workaround?
Olivier
It doesn't seem possible to do this so far. Is there a workaround?
Olivier
Link Copied
5 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Sure there is. Just add the PRIVATE keyword on the line following TYPE. For example:
[plain]type mytype private integer cant_see_me end type mytype[/plain]Now users of the module can see the type, but they can't see the components. Only the module in which mytype is declared can see the components.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Yes, this is true - but doesn't that mean that all the subroutines that access this type need to be declared in the same module as well? Or maybe only their interface needs to be defined in the private section of the module?
If you have many big subroutines that handle instances of the derived type, and if you need to write them in the module where the type is defined, then the module becomes unwieldy.
Do I understand this correctly?
Thanks Steve,
Olivier
If you have many big subroutines that handle instances of the derived type, and if you need to write them in the module where the type is defined, then the module becomes unwieldy.
Do I understand this correctly?
Thanks Steve,
Olivier
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Quoting - opmkl
Yes, this is true - but doesn't that mean that all the subroutines that access this type need to be declared in the same module as well? Or maybe only their interface needs to be defined in the private section of the module?
If you have many big subroutines that handle instances of the derived type, and if you need to write them in the module where the type is defined, then the module becomes unwieldy.
Do I understand this correctly?
Thanks Steve,
Olivier
If you have many big subroutines that handle instances of the derived type, and if you need to write them in the module where the type is defined, then the module becomes unwieldy.
Do I understand this correctly?
Thanks Steve,
Olivier
I don't see the problem here, but you could try something like:
[vb]module mod1
implicit none
private
save
type, public :: mytype
private
integer :: hidden
end type
public set_mytype, handle_mytype, unset_mytype
contains
include './set_mytype.f90'
include './handle_mytype.f90'
include './unset_mytype.f90'
end module mod1[/vb]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Quoting - opmkl
Yes, this is true - but doesn't that mean that all the subroutines that access this type need to be declared in the same module as well? Or maybe only their interface needs to be defined in the private section of the module?
I think you mean't this but being a little more specific: all the procedures that want to access private components of a type need to be in the same module that declares the type. Procedures that access only public components can be in different modules or sub-programs.
In addition to INCLUDE, nesting of types might help. Your top level derived type has a private component that only things in its enclosing module can access, but that component is itself a user defined type with all components having public accessibility.
Some (not tested) code to demonstrate...
[cpp]MODULE ImplentationMod
IMPLICIT NONE
! Everything is public, anyone can play with everything
TYPE :: NestedStuff
INTEGER :: member1
REAL :: member2
! etc...
END TYPE NestedStuff
END MODULE ImplementationMod
MODULE LibraryMod
USE ImplementationMod
IMPLICIT NONE
PRIVATE
PUBLIC :: Op1, Op2
TYPE, PUBLIC :: MyOpaqueHandle
PRIVATE
! Routines that access implementation have to be in this module
TYPE(NestedStuff) :: implementation
! ...perhaps other private members, or some public ones
! that we don't mind the users fiddling with...
END TYPE MyOpaqueHandle
CONTAINS
! perhaps this creates/initialises a MyOpaqueHandle object
SUBROUTINE Op1(this)
USE AnotherModule
TYPE(MyOpaqueHandle), INTENT(OUT) :: this
!******
! Procedures outside this module can't access implementation in
! MyOpaqueHandle variables directly. So we have a series of little
! forwarding routine to expose that implementation member.
CALL Sub1InAnotherModule(this%implementation)
END SUBROUTINE Op1
! Perhaps this does some calcs with a MyOpaqueHandleObject
SUBROUTINE Op2(this, a, b)
USE ADifferentModule
TYPE(MyOpaqueHandle), INTENT(IN) :: this
REAL, INTENT(OUT) :: a, b
!******
! Another forwarding piece
CALL Sub2InADifferentModule(this%implementation, a, b)
! Of course, could be calls of the form...
CALL Sub3InADifferentModule(this%implementation%member1, a, b)
END SUBROUTINE Op2
END MODULE LibraryMod
PROGRAM UserCode
USE LibraryMod
IMPLICIT NONE
TYPE(MyOpaqueHandle) :: thing
REAL arg1, arg2
!******
! Following would give a compile time error message...
! thing%implementation%member1 = ...
! this too...
! call Sub1InAnotherModule(thing%implementation)
! But these are ok, library writer has control
CALL Op1(thing)
CALL Op2(thing, arg1, arg2)
END PROGRAM
[/cpp]
Your gazillions of worker subroutines (in AnotherModule and ADifferentModule and ...) just USE ImplementationMod and can do whatever they please, user code works with the wrapper type MyOpaqueHandle, and must work through the forwarding routines defined in LibraryMod. You do need to write/have the overhead of the LibraryMod forwarding/wrapper layer though.IanH
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Please don't use INCLUDE.
If you have a set of routines to access an opaque type, they must all be contained in the module that declares the type. This is the recommended way of "encapsulating" in Fortran. Other program units that USE the module can declare objects of the type and can pass them as arguments, but can't see inside them.
If you have a set of routines to access an opaque type, they must all be contained in the module that declares the type. This is the recommended way of "encapsulating" in Fortran. Other program units that USE the module can declare objects of the type and can pass them as arguments, but can't see inside them.
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page