Approccio "object oriented" in F90: incapsulamento

È stata già sottolineata l'utilità di limitare le variabili e i metodi della classe a cui l'utente ha accesso per due ragioni: Questa limitazione dell'accesso alle informazioni, nella programmazione OO, è chiamata anche incapsulamento o information hiding.
È noto che F90 permette il massimo controllo sull'accesso a subroutine e a variabili di un modulo attraverso l'attributo PRIVATE, per cui in questo caso non ci sono limiti alle possibilità di information hiding.
MODULE staz_class
IMPLICIT NONE

TYPE staz
...
END TYPE staz

INTEGER :: nc
REAL, PARAMETER :: vk=0.4

PRIVATE nc, vk, mi_vergogno_a_darla_in_giro

CONTAINS
...

SUBROUTINE mi_vergogno_a_darla_in_giro(...)
END SUBROUTINE mi_vergogno_a_darla_in_giro

END MODULE staz_class
Tuttavia, per quanto riguarda i tipi derivati, F90 permette solo 3 possibilità:
  1. il tipo e tutte le sue componenti sono PUBLIC, per cui tutto è consentito
  2. il tipo è PUBLIC, ma tutte le sue componenti sono PRIVATE, per cui il programma che fa USE del modulo (classe) può definire variabili del tipo in questione, passarle ai sottoprogrammi (metodi), ma non può accedere direttamente alle componenti del tipo (ma ovviamente può farlo attaverso opportuni metodi, se ciò è previsto dalla classe)
  3. il tipo è PRIVATE e quindi inutilizzabile fuori dal modulo, ma questo caso non ci interessa
Non è quindi possibile definire come privati solo un sottoinsieme delle variabili delle istanze di una classe (lo sarà, al solito, in F2003), per cui dobbiamo scegliere un approccio estremo.

L'approccio del punto 2. è consigliato nel caso di classi con poche variabili e di tipo scalare, in questo caso possiamo negare l'accesso a tutti i membri del tipo e fornire dei metodi che permettano di modificarlo in maniera controllata e di ricevere il minimo di informazioni necessarie sullo stato dell'istanza.

MODULE geo_coord_class
IMPLICIT NONE

TYPE geo_coord
  PRIVATE
  REAL :: lon, lat
  DOUBLE PRECISION :: utme, utmn
  INTEGER :: fuso
  CHARACTER(LEN=20) :: elliss
END TYPE staz

INTERFACE get_lon
  MODULE PROCEDURE geo_coord_get_lon
END INTERFACE

INTERFACE set_lonlat
  MODULE PROCEDURE geo_coord_set_lonlat
END INTERFACE

...

PRIVATE lonlat_to_utm

CONTAINS
...

FUNCTION geo_coord_get_lon(this) RESULT(lon)
TYPE(geo_coord), INTENT(OUT) :: this
REAL :: lon

lon = this%lon

END FUNCTION geo_coord_get_lon

SUBROUTINE geo_coord_set_lonlat(this, lon, lat)
TYPE(geo_coord), INTENT(IN) :: this
REAL, INTENT(IN) :: lon, lat

this%lon = lon
this%lat = lat

CALL lonlat_to_utm(this)

END SUBROUTINE geo_coord_set_lonlat

...
END MODULE geo_coord_class
PROGRAM elab_coord
USE geo_coord
TYPE(coord) :: mycoord
REAL :: lon, lat

CALL set_lonlat(mycoord, lon, lat)
PRINT*,'longitudine:', get_lon(mycoord)
!PRINT*,'longitudine:', mycoord%lon ! vietato!

END PROGRAM elab_coord
D'altra parte, nel caso di classi con molte variabili o che contengono array, magari allocati dinamicamente, l'approccio 2. è macchinoso e poco efficiente, per cui in questo caso è meglio usare l'approccio 1., dando potenziale accesso a tutte le variabili dell'istanza, ma documentando comunque le eventuali operazioni che non sono consentite sui dati della classe.
MODULE staz_class
IMPLICIT NONE

TYPE staz
  REAL, POINTER :: obs(:,:)
  ...
END TYPE staz

CONTAINS
...
END MODULE staz_class
PROGRAM elab_staz
USE staz_class
IMPLICIT NONE

TYPE(staz) :: mystaz
...

med = mystaz%obs(1:) / COUNT(mystaz%obs(1:))

END PROGRAM staz_class