Les references de donnees en ABAP sont des pointeurs types qui pointent vers des objets de donnees en memoire. Contrairement aux Field-Symbols, qui pointent directement vers la memoire, les references de donnees sont des variables autonomes qui stockent une adresse.
Concept de base
- Une reference de donnees est une variable qui contient l’adresse memoire d’un objet de donnees
- Elle peut etre transmise, stockee et comparee
- L’acces aux donnees se fait par dereferencement (
->*) - Les references de donnees peuvent etre initiales (NULL)
Syntaxe
Declarer une reference de donnees
" Reference typeeDATA: lr_data TYPE REF TO <type_donnees>.
" Reference generique (vers des donnees quelconques)DATA: lr_any TYPE REF TO data.
" Declaration inlineDATA(lr_inline) = REF #( variable ).Creer une reference
" Moderne (depuis 7.40) : REF #()lr_data = REF #( variable ).
" Classique : GET REFERENCEGET REFERENCE OF variable INTO lr_data.
" Creer un nouvel objet de donneesCREATE DATA lr_data TYPE <typ>.lr_data = NEW #( ). " Depuis 7.40Dereferencement
" Acces aux donnees<valeur> = lr_data->*.
" Pour les structures : acces aux composants<valeur> = lr_struct->comp_name.
" Pour les tables : acces aux lignesLOOP AT lr_table->* INTO DATA(ls_line). ...ENDLOOP.Champs systeme
Apres les operations avec les references de donnees :
- Reference
IS BOUND: pointe vers des donnees valides - Reference
IS INITIAL: ne pointe vers rien (NULL)
Exemples
1. Utilisation de base
DATA: lv_number TYPE i VALUE 42.DATA: lr_number TYPE REF TO i.
" Creer une reference vers une variablelr_number = REF #( lv_number ).
" Dereferencement : lire la valeurWRITE: / 'Valeur:', lr_number->*. " 42
" Dereferencement : modifier la valeurlr_number->* = 100.WRITE: / 'Original:', lv_number. " 100 (modifie !)2. Verifier une reference
DATA: lr_data TYPE REF TO string.
" Verifier si la reference est valideIF lr_data IS BOUND. WRITE: / 'La reference pointe vers:', lr_data->*.ELSE. WRITE: / 'La reference est NULL'.ENDIF.
IF lr_data IS INITIAL. WRITE: / 'Reference non initialisee'.ENDIF.
" Liberer la referenceFREE lr_data.3. GET REFERENCE (syntaxe classique)
DATA: lv_text TYPE string VALUE 'Bonjour le monde'.DATA: lr_text TYPE REF TO string.
" Syntaxe classiqueGET REFERENCE OF lv_text INTO lr_text.
WRITE: / lr_text->*. " Bonjour le monde4. Creer un nouvel objet de donnees
DATA: lr_number TYPE REF TO i.
" Classique : CREATE DATACREATE DATA lr_number.lr_number->* = 42.
" Moderne : NEW #()DATA(lr_string) = NEW string( 'Nouvelle chaine' ).WRITE: / lr_string->*.
" Avec typeDATA: lr_any TYPE REF TO data.CREATE DATA lr_any TYPE i.
" Generique avec type dynamiqueDATA: lv_typename TYPE string VALUE 'STRING'.CREATE DATA lr_any TYPE (lv_typename).5. References avec tables internes
TYPES: BEGIN OF ty_customer, id TYPE i, name TYPE string, END OF ty_customer.
DATA: lt_customers TYPE TABLE OF ty_customer, lr_table TYPE REF TO ty_customer.
lt_customers = VALUE #( ( id = 1 name = 'Muller' ) ( id = 2 name = 'Schmidt' )).
" REFERENCE INTO dans LOOPLOOP AT lt_customers REFERENCE INTO lr_table. WRITE: / lr_table->id, lr_table->name.
" Modification via reference lr_table->name = to_upper( lr_table->name ).ENDLOOP.
" READ TABLE avec REFERENCE INTOREAD TABLE lt_customers REFERENCE INTO lr_table WITH KEY id = 1.
IF sy-subrc = 0. lr_table->name = 'Modifie'.ENDIF.6. Stocker des references dans des tables
DATA: lt_refs TYPE TABLE OF REF TO string.DATA: lv_str1 TYPE string VALUE 'Un', lv_str2 TYPE string VALUE 'Deux', lv_str3 TYPE string VALUE 'Trois'.
" Collecter des referencesAPPEND REF #( lv_str1 ) TO lt_refs.APPEND REF #( lv_str2 ) TO lt_refs.APPEND REF #( lv_str3 ) TO lt_refs.
" Parcourir les referencesLOOP AT lt_refs INTO DATA(lr_str). WRITE: / lr_str->*.ENDLOOP.
" Modifier les valeurs originales via les referencesREAD TABLE lt_refs INTO lr_str INDEX 1.lr_str->* = 'MODIFIE'.WRITE: / lv_str1. " MODIFIE7. Passer des references aux methodes
CLASS lcl_processor DEFINITION. PUBLIC SECTION. METHODS: process_data IMPORTING ir_data TYPE REF TO i.ENDCLASS.
CLASS lcl_processor IMPLEMENTATION. METHOD process_data. IF ir_data IS BOUND. ir_data->* = ir_data->* * 2. ENDIF. ENDMETHOD.ENDCLASS.
" UtilisationDATA: lv_value TYPE i VALUE 50, lo_proc TYPE REF TO lcl_processor.
lo_proc = NEW #( ).lo_proc->process_data( REF #( lv_value ) ).
WRITE: / lv_value. " 1008. References generiques (REF TO data)
DATA: lr_any TYPE REF TO data.FIELD-SYMBOLS: <fs_data> TYPE any.
" Reference vers IntegerDATA(lv_int) = 42.lr_any = REF #( lv_int ).
" Pour l'acces : assigner un Field-SymbolASSIGN lr_any->* TO <fs_data>.WRITE: / <fs_data>.
" Reference vers StringDATA(lv_str) = |Bonjour|.lr_any = REF #( lv_str ).
ASSIGN lr_any->* TO <fs_data>.WRITE: / <fs_data>.9. Creation dynamique d’objets
DATA: lr_data TYPE REF TO data, lv_type TYPE string VALUE 'STRING'.
" Creer dynamiquement un objet de donneesCREATE DATA lr_data TYPE (lv_type).
" Assigner une valeur via Field-SymbolFIELD-SYMBOLS: <fs> TYPE any.ASSIGN lr_data->* TO <fs>.<fs> = 'Cree dynamiquement'.
WRITE: / <fs>.
" Pour les structuresDATA: lv_struct_name TYPE string VALUE 'SFLIGHT'.CREATE DATA lr_data TYPE (lv_struct_name).ASSIGN lr_data->* TO <fs>.10. Comparaison de references
DATA: lv_data TYPE string VALUE 'Test'.DATA: lr_ref1 TYPE REF TO string, lr_ref2 TYPE REF TO string, lr_ref3 TYPE REF TO string.
lr_ref1 = REF #( lv_data ).lr_ref2 = REF #( lv_data ).lr_ref3 = lr_ref1.
" Comparaison de references (pointent vers la meme adresse ?)IF lr_ref1 = lr_ref3. WRITE: / 'ref1 et ref3 sont identiques'. " OuiENDIF.
IF lr_ref1 = lr_ref2. WRITE: / 'ref1 et ref2 sont identiques'. " Non ! (references differentes)ENDIF.
" Comparaison de valeursIF lr_ref1->* = lr_ref2->*. WRITE: / 'Les valeurs sont egales'. " OuiENDIF.Reference de donnees vs Field-Symbol
| Aspect | Reference de donnees | Field-Symbol |
|---|---|---|
| Type | Variable (REF TO) | Espace reserve |
| Stockage | Oui, peut etre stockee | Non, seulement temporaire |
| Transmission | Peut etre passee en parametre | Utilisable localement seulement |
| Etat NULL | Peut etre initial/non liee | Non assignee |
| Syntaxe | lr_data->* | <fs> |
| Performance | Legerement plus lent | Legerement plus rapide |
| Application | Stockage, transmission | Acces local rapide |
" Field-Symbol : acces local rapideLOOP AT lt_data ASSIGNING FIELD-SYMBOL(<fs>). <fs>-field = 'X'.ENDLOOP.
" Reference de donnees : quand la reference doit etre stockeeLOOP AT lt_data REFERENCE INTO DATA(lr_line). APPEND lr_line TO lt_references. " Stocker la referenceENDLOOP.Cas d’utilisation typiques
1. Parametres optionnels
METHODS: process IMPORTING ir_config TYPE REF TO ty_config OPTIONAL.
METHOD process. IF ir_config IS BOUND. " Utiliser la configuration ELSE. " Valeurs par defaut ENDIF.ENDMETHOD.2. Retour de references
METHODS: get_instance RETURNING VALUE(rr_instance) TYPE REF TO lcl_singleton.
METHOD get_instance. IF gr_instance IS NOT BOUND. gr_instance = NEW #( ). ENDIF. rr_instance = gr_instance.ENDMETHOD.3. Structures de donnees dynamiques
" Structure arborescente avec referencesTYPES: BEGIN OF ty_node, value TYPE string, children TYPE TABLE OF REF TO ty_node WITH EMPTY KEY, END OF ty_node.
DATA: lr_root TYPE REF TO ty_node.lr_root = NEW #( value = 'Racine' ).APPEND NEW ty_node( value = 'Enfant 1' ) TO lr_root->children.Remarques importantes / Bonnes pratiques
- Verifiez toujours
IS BOUNDavant le dereferencement. - Utilisez
REF #()au lieu deGET REFERENCEdans l’ABAP moderne. - Les Field-Symbols sont plus performants pour l’acces local.
- Les references de donnees sont necessaires lorsque les references doivent etre stockees ou transmises.
CREATE DATApour la determination dynamique du type a l’execution.- Attention aux references generiques (
REF TO data) - la securite de type est perdue. - Combinez avec
LOOP AT ... REFERENCE INTOpour un acces efficace aux tables. - Utilisez les references dans les attributs de
CLASSpour les relations entre objets.