L’instruction CLASS est le fondement de la programmation orientée objet (POO) en ABAP. Avec les classes, vous pouvez regrouper des données (attributs) et des fonctions (méthodes) dans des unités réutilisables.
Concept de base
Une classe est un modèle (Blueprint) pour les objets. Elle définit :
- Attributs : Variables qui stockent l’état d’un objet
- Méthodes : Fonctions qui définissent le comportement d’un objet
Un objet est une instance concrète d’une classe.
Syntaxe
Définition de classe
CLASS <nom_classe> DEFINITION. PUBLIC SECTION. " Éléments accessibles publiquement DATA: <attribut> TYPE <type>. METHODS: <methode> [IMPORTING/EXPORTING/RETURNING ...].
PROTECTED SECTION. " Accessible uniquement pour cette classe et les sous-classes
PRIVATE SECTION. " Accessible uniquement dans cette classeENDCLASS.Implémentation de classe
CLASS <nom_classe> IMPLEMENTATION. METHOD <methode>. " Logique de la méthode ENDMETHOD.ENDCLASS.Niveaux de visibilité
| Section | Accès |
|---|---|
PUBLIC | Accessible de partout |
PROTECTED | Uniquement classe elle-même et sous-classes |
PRIVATE | Uniquement dans la classe |
Exemples
1. Définir et utiliser une classe simple
" DéfinitionCLASS lcl_counter DEFINITION. PUBLIC SECTION. METHODS: increment, get_value RETURNING VALUE(rv_value) TYPE i. PRIVATE SECTION. DATA: mv_count TYPE i VALUE 0.ENDCLASS.
" ImplémentationCLASS lcl_counter IMPLEMENTATION. METHOD increment. mv_count = mv_count + 1. ENDMETHOD.
METHOD get_value. rv_value = mv_count. ENDMETHOD.ENDCLASS.
" UtilisationSTART-OF-SELECTION. DATA: lo_counter TYPE REF TO lcl_counter.
" Créer l'objet CREATE OBJECT lo_counter. " Ou moderne : lo_counter = NEW #( ).
lo_counter->increment( ). lo_counter->increment( ).
WRITE: / 'Compteur :', lo_counter->get_value( ). " Sortie : Compteur : 22. Classe avec constructeur
Le constructeur est une méthode spéciale appelée automatiquement lors de la création d’un objet :
CLASS lcl_person DEFINITION. PUBLIC SECTION. METHODS: constructor IMPORTING iv_name TYPE string iv_age TYPE i, get_info RETURNING VALUE(rv_info) TYPE string. PRIVATE SECTION. DATA: mv_name TYPE string, mv_age TYPE i.ENDCLASS.
CLASS lcl_person IMPLEMENTATION. METHOD constructor. mv_name = iv_name. mv_age = iv_age. ENDMETHOD.
METHOD get_info. rv_info = |{ mv_name } a { mv_age } ans.|. ENDMETHOD.ENDCLASS.
" UtilisationDATA: lo_person TYPE REF TO lcl_person.
" Créer l'objet avec paramètres du constructeurlo_person = NEW #( iv_name = 'Max Müller' iv_age = 30 ).
WRITE: / lo_person->get_info( )." Sortie : Max Müller a 30 ans.3. Méthodes avec paramètres
CLASS lcl_calculator DEFINITION. PUBLIC SECTION. METHODS: add IMPORTING iv_a TYPE i iv_b TYPE i RETURNING VALUE(rv_result) TYPE i,
divide IMPORTING iv_dividend TYPE i iv_divisor TYPE i EXPORTING ev_result TYPE f RAISING cx_sy_zerodivide.ENDCLASS.
CLASS lcl_calculator IMPLEMENTATION. METHOD add. rv_result = iv_a + iv_b. ENDMETHOD.
METHOD divide. IF iv_divisor = 0. RAISE EXCEPTION TYPE cx_sy_zerodivide. ENDIF. ev_result = iv_dividend / iv_divisor. ENDMETHOD.ENDCLASS.
" UtilisationDATA: lo_calc TYPE REF TO lcl_calculator, lv_sum TYPE i, lv_quot TYPE f.
lo_calc = NEW #( ).
" Paramètre RETURNING : Méthode fonctionnellelv_sum = lo_calc->add( iv_a = 5 iv_b = 3 ).WRITE: / 'Somme :', lv_sum.
" Paramètre EXPORTINGlo_calc->divide( EXPORTING iv_dividend = 10 iv_divisor = 4 IMPORTING ev_result = lv_quot ).WRITE: / 'Quotient :', lv_quot.4. Méthodes et attributs statiques (CLASS-DATA/CLASS-METHODS)
Les éléments statiques appartiennent à la classe elle-même, pas aux objets individuels :
CLASS lcl_id_generator DEFINITION. PUBLIC SECTION. CLASS-METHODS: get_next_id RETURNING VALUE(rv_id) TYPE i. PRIVATE SECTION. CLASS-DATA: gv_counter TYPE i VALUE 0.ENDCLASS.
CLASS lcl_id_generator IMPLEMENTATION. METHOD get_next_id. gv_counter = gv_counter + 1. rv_id = gv_counter. ENDMETHOD.ENDCLASS.
" Utilisation - aucun objet nécessaire !DATA: lv_id1 TYPE i, lv_id2 TYPE i.
lv_id1 = lcl_id_generator=>get_next_id( ). " => pour appel statiquelv_id2 = lcl_id_generator=>get_next_id( ).
WRITE: / 'ID 1:', lv_id1. " 1WRITE: / 'ID 2:', lv_id2. " 25. Héritage
Avec INHERITING FROM, une classe peut hériter d’une autre :
" Classe de baseCLASS lcl_vehicle DEFINITION. PUBLIC SECTION. METHODS: constructor IMPORTING iv_brand TYPE string, get_brand RETURNING VALUE(rv_brand) TYPE string. PROTECTED SECTION. DATA: mv_brand TYPE string.ENDCLASS.
CLASS lcl_vehicle IMPLEMENTATION. METHOD constructor. mv_brand = iv_brand. ENDMETHOD.
METHOD get_brand. rv_brand = mv_brand. ENDMETHOD.ENDCLASS.
" Classe dérivéeCLASS lcl_car DEFINITION INHERITING FROM lcl_vehicle. PUBLIC SECTION. METHODS: constructor IMPORTING iv_brand TYPE string iv_doors TYPE i, get_info RETURNING VALUE(rv_info) TYPE string. PRIVATE SECTION. DATA: mv_doors TYPE i.ENDCLASS.
CLASS lcl_car IMPLEMENTATION. METHOD constructor. " Appeler le constructeur de la classe parente super->constructor( iv_brand = iv_brand ). mv_doors = iv_doors. ENDMETHOD.
METHOD get_info. rv_info = |{ mv_brand } avec { mv_doors } portes|. ENDMETHOD.ENDCLASS.
" UtilisationDATA: lo_car TYPE REF TO lcl_car.
lo_car = NEW #( iv_brand = 'BMW' iv_doors = 4 ).WRITE: / lo_car->get_info( )." Sortie : BMW avec 4 portes6. Redéfinition de méthodes (REDEFINITION)
CLASS lcl_animal DEFINITION. PUBLIC SECTION. METHODS: speak RETURNING VALUE(rv_sound) TYPE string.ENDCLASS.
CLASS lcl_animal IMPLEMENTATION. METHOD speak. rv_sound = 'Bruit'. ENDMETHOD.ENDCLASS.
CLASS lcl_dog DEFINITION INHERITING FROM lcl_animal. PUBLIC SECTION. METHODS: speak REDEFINITION.ENDCLASS.
CLASS lcl_dog IMPLEMENTATION. METHOD speak. rv_sound = 'Woof!'. ENDMETHOD.ENDCLASS.
" UtilisationDATA: lo_animal TYPE REF TO lcl_animal, lo_dog TYPE REF TO lcl_dog.
lo_animal = NEW lcl_animal( ).lo_dog = NEW lcl_dog( ).
WRITE: / 'Animal:', lo_animal->speak( ). " BruitWRITE: / 'Chien:', lo_dog->speak( ). " Woof!Types de paramètres de méthode
| Type | Description | Syntaxe |
|---|---|---|
IMPORTING | Paramètre d’entrée | IMPORTING iv_param TYPE type |
EXPORTING | Paramètre de sortie | EXPORTING ev_param TYPE type |
CHANGING | Entrée et sortie | CHANGING cv_param TYPE type |
RETURNING | Valeur de retour (fonctionnel) | RETURNING VALUE(rv_param) TYPE type |
RAISING | Exceptions possibles | RAISING cx_exception |
Création d’objets
DATA: lo_obj TYPE REF TO lcl_myclass.
" Syntaxe classiqueCREATE OBJECT lo_obj.
" Avec paramètresCREATE OBJECT lo_obj EXPORTING iv_param = 'Valeur'.
" Syntaxe moderne (à partir de 7.40)lo_obj = NEW #( ).lo_obj = NEW #( iv_param = 'Valeur' ).
" Déclaration en ligneDATA(lo_obj2) = NEW lcl_myclass( iv_param = 'Valeur' ).Classes globales vs. locales
| Type | Définition | Utilisation |
|---|---|---|
| Locale | Dans le programme avec CLASS ... DEFINITION | Uniquement dans le même programme |
| Globale | Dans le Class Builder (SE24) | Disponible dans tout le système |
Les classes locales commencent souvent par lcl_ (local class), les globales par zcl_ ou cl_.
Classes et méthodes abstraites
Les classes abstraites ne peuvent pas être instanciées :
CLASS lcl_shape DEFINITION ABSTRACT. PUBLIC SECTION. METHODS: get_area ABSTRACT RETURNING VALUE(rv_area) TYPE f.ENDCLASS.
CLASS lcl_rectangle DEFINITION INHERITING FROM lcl_shape. PUBLIC SECTION. METHODS: constructor IMPORTING iv_width TYPE f iv_height TYPE f, get_area REDEFINITION. PRIVATE SECTION. DATA: mv_width TYPE f, mv_height TYPE f.ENDCLASS.
CLASS lcl_rectangle IMPLEMENTATION. METHOD constructor. mv_width = iv_width. mv_height = iv_height. ENDMETHOD.
METHOD get_area. rv_area = mv_width * mv_height. ENDMETHOD.ENDCLASS.Remarques importantes / Bonnes pratiques
- Utilisez des noms parlants pour les classes et méthodes.
- Gardez les méthodes courtes et focalisées (Single Responsibility).
- Utilisez PRIVATE pour les données internes pour assurer l’encapsulation.
- Les paramètres RETURNING permettent les appels fonctionnels et le chaînage.
- Pour un comportement polymorphe, utilisez
INTERFACEau lieu d’héritage. - Gérez les erreurs avec
TRY...CATCHet exceptions. - Préférez la syntaxe moderne
NEW #( )pour la création d’objets. - Les classes globales (SE24) sont réutilisables et testables.