La sentencia CLASS es el fundamento de la programacion orientada a objetos (POO) en ABAP. Con clases puedes agrupar datos (atributos) y funciones (metodos) en unidades reutilizables.
Concepto basico
Una clase es una plantilla (blueprint) para objetos. Define:
- Atributos: Variables que almacenan el estado de un objeto
- Metodos: Funciones que definen el comportamiento de un objeto
Un objeto es una instancia concreta de una clase.
Sintaxis
Definicion de clase
CLASS <nombre_clase> DEFINITION. PUBLIC SECTION. " Elementos accesibles publicamente DATA: <atributo> TYPE <tipo>. METHODS: <metodo> [IMPORTING/EXPORTING/RETURNING ...].
PROTECTED SECTION. " Solo accesible para esta clase y subclases
PRIVATE SECTION. " Solo accesible dentro de esta claseENDCLASS.Implementacion de clase
CLASS <nombre_clase> IMPLEMENTATION. METHOD <metodo>. " Logica del metodo ENDMETHOD.ENDCLASS.Areas de visibilidad
| Area | Acceso |
|---|---|
PUBLIC | Accesible desde cualquier lugar |
PROTECTED | Solo la clase misma y subclases |
PRIVATE | Solo dentro de la clase |
Ejemplos
1. Definir y usar una clase simple
" DefinicionCLASS 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.
" ImplementacionCLASS lcl_counter IMPLEMENTATION. METHOD increment. mv_count = mv_count + 1. ENDMETHOD.
METHOD get_value. rv_value = mv_count. ENDMETHOD.ENDCLASS.
" UsoSTART-OF-SELECTION. DATA: lo_counter TYPE REF TO lcl_counter.
" Crear objeto CREATE OBJECT lo_counter. " O moderno: lo_counter = NEW #( ).
lo_counter->increment( ). lo_counter->increment( ).
WRITE: / 'Contador:', lo_counter->get_value( ). " Salida: Contador: 22. Clase con constructor
El constructor es un metodo especial que se llama automaticamente al crear un objeto:
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 } tiene { mv_age } anos.|. ENDMETHOD.ENDCLASS.
" UsoDATA: lo_person TYPE REF TO lcl_person.
" Crear objeto con parametros del constructorlo_person = NEW #( iv_name = 'Max Muller' iv_age = 30 ).
WRITE: / lo_person->get_info( )." Salida: Max Muller tiene 30 anos.3. Metodos con parametros
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.
" UsoDATA: lo_calc TYPE REF TO lcl_calculator, lv_sum TYPE i, lv_quot TYPE f.
lo_calc = NEW #( ).
" Parametro RETURNING: Metodo funcionallv_sum = lo_calc->add( iv_a = 5 iv_b = 3 ).WRITE: / 'Suma:', lv_sum.
" Parametro EXPORTINGlo_calc->divide( EXPORTING iv_dividend = 10 iv_divisor = 4 IMPORTING ev_result = lv_quot ).WRITE: / 'Cociente:', lv_quot.4. Metodos y atributos estaticos (CLASS-DATA/CLASS-METHODS)
Los elementos estaticos pertenecen a la clase misma, no a objetos individuales:
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.
" Uso - no se necesita objeto!DATA: lv_id1 TYPE i, lv_id2 TYPE i.
lv_id1 = lcl_id_generator=>get_next_id( ). " => para llamada estaticalv_id2 = lcl_id_generator=>get_next_id( ).
WRITE: / 'ID 1:', lv_id1. " 1WRITE: / 'ID 2:', lv_id2. " 25. Herencia
Con INHERITING FROM una clase puede heredar de otra:
" Clase 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.
" Clase derivadaCLASS 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. " Llamar constructor de la clase padre super->constructor( iv_brand = iv_brand ). mv_doors = iv_doors. ENDMETHOD.
METHOD get_info. rv_info = |{ mv_brand } con { mv_doors } puertas|. ENDMETHOD.ENDCLASS.
" UsoDATA: lo_car TYPE REF TO lcl_car.
lo_car = NEW #( iv_brand = 'BMW' iv_doors = 4 ).WRITE: / lo_car->get_info( )." Salida: BMW con 4 puertas6. Sobrescribir metodos (REDEFINITION)
CLASS lcl_animal DEFINITION. PUBLIC SECTION. METHODS: speak RETURNING VALUE(rv_sound) TYPE string.ENDCLASS.
CLASS lcl_animal IMPLEMENTATION. METHOD speak. rv_sound = 'Sonido'. ENDMETHOD.ENDCLASS.
CLASS lcl_dog DEFINITION INHERITING FROM lcl_animal. PUBLIC SECTION. METHODS: speak REDEFINITION.ENDCLASS.
CLASS lcl_dog IMPLEMENTATION. METHOD speak. rv_sound = 'Guau!'. ENDMETHOD.ENDCLASS.
" UsoDATA: 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( ). " SonidoWRITE: / 'Perro:', lo_dog->speak( ). " Guau!Tipos de parametros de metodos
| Tipo | Descripcion | Sintaxis |
|---|---|---|
IMPORTING | Parametro de entrada | IMPORTING iv_param TYPE tipo |
EXPORTING | Parametro de salida | EXPORTING ev_param TYPE tipo |
CHANGING | Entrada y salida | CHANGING cv_param TYPE tipo |
RETURNING | Valor de retorno (funcional) | RETURNING VALUE(rv_param) TYPE tipo |
RAISING | Excepciones posibles | RAISING cx_exception |
Creacion de objetos
DATA: lo_obj TYPE REF TO lcl_myclass.
" Sintaxis clasicaCREATE OBJECT lo_obj.
" Con parametrosCREATE OBJECT lo_obj EXPORTING iv_param = 'Valor'.
" Sintaxis moderna (desde 7.40)lo_obj = NEW #( ).lo_obj = NEW #( iv_param = 'Valor' ).
" Declaracion inlineDATA(lo_obj2) = NEW lcl_myclass( iv_param = 'Valor' ).Clases globales vs. locales
| Tipo | Definicion | Uso |
|---|---|---|
| Local | En el programa con CLASS ... DEFINITION | Solo en el mismo programa |
| Global | En el Class Builder (SE24) | Disponible en todo el sistema |
Las clases locales frecuentemente comienzan con lcl_ (local class), las globales con zcl_ o cl_.
Clases y metodos abstractos
Las clases abstractas no pueden ser instanciadas:
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.Notas importantes / Mejores practicas
- Utiliza nombres descriptivos para clases y metodos.
- Mantén los metodos cortos y enfocados (Single Responsibility).
- Usa PRIVATE para datos internos, garantizando el encapsulamiento.
- Parametros RETURNING permiten llamadas funcionales y encadenamiento.
- Para comportamiento polimorfico usa
INTERFACEen lugar de herencia. - Maneja errores con
TRY...CATCHy excepciones. - Prefiere la sintaxis moderna
NEW #( )para creacion de objetos. - Las clases globales (SE24) son reutilizables y testeables.