ABAP CLASS et METHOD : Programmation orientée objet

Catégorie
ABAP-Statements
Publié
Auteur
Johannes

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 classe
ENDCLASS.

Implémentation de classe

CLASS <nom_classe> IMPLEMENTATION.
METHOD <methode>.
" Logique de la méthode
ENDMETHOD.
ENDCLASS.

Niveaux de visibilité

SectionAccès
PUBLICAccessible de partout
PROTECTEDUniquement classe elle-même et sous-classes
PRIVATEUniquement dans la classe

Exemples

1. Définir et utiliser une classe simple

" Définition
CLASS 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émentation
CLASS lcl_counter IMPLEMENTATION.
METHOD increment.
mv_count = mv_count + 1.
ENDMETHOD.
METHOD get_value.
rv_value = mv_count.
ENDMETHOD.
ENDCLASS.
" Utilisation
START-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 : 2

2. 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.
" Utilisation
DATA: lo_person TYPE REF TO lcl_person.
" Créer l'objet avec paramètres du constructeur
lo_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.
" Utilisation
DATA: lo_calc TYPE REF TO lcl_calculator,
lv_sum TYPE i,
lv_quot TYPE f.
lo_calc = NEW #( ).
" Paramètre RETURNING : Méthode fonctionnelle
lv_sum = lo_calc->add( iv_a = 5 iv_b = 3 ).
WRITE: / 'Somme :', lv_sum.
" Paramètre EXPORTING
lo_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 statique
lv_id2 = lcl_id_generator=>get_next_id( ).
WRITE: / 'ID 1:', lv_id1. " 1
WRITE: / 'ID 2:', lv_id2. " 2

5. Héritage

Avec INHERITING FROM, une classe peut hériter d’une autre :

" Classe de base
CLASS 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ée
CLASS 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.
" Utilisation
DATA: 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 portes

6. 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.
" Utilisation
DATA: 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( ). " Bruit
WRITE: / 'Chien:', lo_dog->speak( ). " Woof!

Types de paramètres de méthode

TypeDescriptionSyntaxe
IMPORTINGParamètre d’entréeIMPORTING iv_param TYPE type
EXPORTINGParamètre de sortieEXPORTING ev_param TYPE type
CHANGINGEntrée et sortieCHANGING cv_param TYPE type
RETURNINGValeur de retour (fonctionnel)RETURNING VALUE(rv_param) TYPE type
RAISINGExceptions possiblesRAISING cx_exception

Création d’objets

DATA: lo_obj TYPE REF TO lcl_myclass.
" Syntaxe classique
CREATE OBJECT lo_obj.
" Avec paramètres
CREATE 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 ligne
DATA(lo_obj2) = NEW lcl_myclass( iv_param = 'Valeur' ).

Classes globales vs. locales

TypeDéfinitionUtilisation
LocaleDans le programme avec CLASS ... DEFINITIONUniquement dans le même programme
GlobaleDans 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 INTERFACE au lieu d’héritage.
  • Gérez les erreurs avec TRY...CATCH et exceptions.
  • Préférez la syntaxe moderne NEW #( ) pour la création d’objets.
  • Les classes globales (SE24) sont réutilisables et testables.