ABAP Classes and Methods
ABAP's object orientation is close enough to Java or C# to feel familiar and different enough to trip you up. The two differences that matter immediately: a class is split into a definition and an implementation, and method parameters are named and directional rather than positional. Local classes need no repository, so everything here runs in a browser.
Definition and implementation
CLASS ... DEFINITION declares what exists; the matching
CLASS ... IMPLEMENTATION supplies the bodies. A class starting with
lcl_ is a local class, visible only inside this program — which is why it
works without an SAP system.
CLASS lcl_calculator DEFINITION.
PUBLIC SECTION.
METHODS add
IMPORTING iv_a TYPE i
iv_b TYPE i
RETURNING VALUE(rv_result) TYPE i.
ENDCLASS.
CLASS lcl_calculator IMPLEMENTATION.
METHOD add.
rv_result = iv_a + iv_b.
ENDMETHOD.
ENDCLASS.
PUBLIC SECTION, PROTECTED SECTION and
PRIVATE SECTION group members by visibility instead of marking each one,
and they must appear in that order.
Method parameters are named and directional
This is the part with no real equivalent in most languages. Every parameter has a direction:
IMPORTING— comes in, read-only inside the methodEXPORTING— goes out, cleared on entryCHANGING— comes in and goes outRETURNING VALUE(...)— a single return value, and the only form that lets the call be used as an expressionRAISING— the exceptions it may raise
Prefer RETURNING for a single result: it is what makes
lv_x = lo_calc->add( ... ) and method chaining possible.
A method can have RETURNING or EXPORTING,
not both.
" Named arguments at the call site
lv_sum = lo_calc->add( iv_a = 10 iv_b = 20 ).
" With exactly one importing parameter, the name may be omitted
lv_text = lo_greeter->greet( 'ABAP' ).
Creating objects: CREATE OBJECT and NEW
A reference variable is TYPE REF TO the class. Classic ABAP creates the
instance with CREATE OBJECT; since 7.40 the
NEW operator does the same in an expression, which is what modern code uses.
" Classic
DATA lo_calc TYPE REF TO lcl_calculator.
CREATE OBJECT lo_calc.
" Modern — declaration and creation in one line
DATA(lo_calc2) = NEW lcl_calculator( ).
" A reference starts unbound; calling a method on it dumps
IF lo_calc IS BOUND.
WRITE / 'safe to call'.
ENDIF.
Constructors and instance state
The constructor is a method literally named constructor. Its
IMPORTING parameters are passed when the object is created.
Attributes declared under DATA inside the class are instance state;
keeping them private and exposing behaviour instead is the usual convention.
CLASS lcl_counter DEFINITION.
PUBLIC SECTION.
METHODS constructor IMPORTING iv_start TYPE i.
METHODS increment RETURNING VALUE(rv_value) TYPE i.
PRIVATE SECTION.
DATA mv_value TYPE i.
ENDCLASS.
CLASS lcl_counter IMPLEMENTATION.
METHOD constructor.
mv_value = iv_start.
ENDMETHOD.
METHOD increment.
mv_value = mv_value + 1.
rv_value = mv_value.
ENDMETHOD.
ENDCLASS.
DATA(lo_counter) = NEW lcl_counter( iv_start = 10 ).
WRITE / lo_counter->increment( ). " 11
The mv_ prefix for member variables and iv_
for importing parameters are conventions, not rules — but they are near-universal in ABAP code, and following
them makes your code readable to the next person.
Interfaces and inheritance
Interfaces are declared separately and implemented with INTERFACES.
Note that the method is then referred to with a tilde: if_name~method.
Inheritance uses INHERITING FROM, and an overriding method must say
REDEFINITION — ABAP will not let you override by accident.
INTERFACE lif_shape.
METHODS area RETURNING VALUE(rv_area) TYPE f.
ENDINTERFACE.
CLASS lcl_square DEFINITION.
PUBLIC SECTION.
INTERFACES lif_shape.
METHODS constructor IMPORTING iv_side TYPE f.
PRIVATE SECTION.
DATA mv_side TYPE f.
ENDCLASS.
CLASS lcl_square IMPLEMENTATION.
METHOD constructor.
mv_side = iv_side.
ENDMETHOD.
METHOD lif_shape~area.
rv_area = mv_side * mv_side.
ENDMETHOD.
ENDCLASS.
DATA li_shape TYPE REF TO lif_shape.
li_shape = NEW lcl_square( iv_side = '3.0' ).
WRITE / li_shape->area( ).
Full example
A complete program with two methods, both using RETURNING.
Run it, then add a subtract method of your own.
REPORT ztest_oo.
CLASS lcl_calculator DEFINITION.
PUBLIC SECTION.
METHODS add
IMPORTING iv_a TYPE i
iv_b TYPE i
RETURNING VALUE(rv_result) TYPE i.
METHODS multiply
IMPORTING iv_a TYPE i
iv_b TYPE i
RETURNING VALUE(rv_result) TYPE i.
ENDCLASS.
CLASS lcl_calculator IMPLEMENTATION.
METHOD add.
rv_result = iv_a + iv_b.
ENDMETHOD.
METHOD multiply.
rv_result = iv_a * iv_b.
ENDMETHOD.
ENDCLASS.
DATA lo_calc TYPE REF TO lcl_calculator.
CREATE OBJECT lo_calc.
DATA lv_sum TYPE i.
DATA lv_product TYPE i.
lv_sum = lo_calc->add( iv_a = 10 iv_b = 20 ).
lv_product = lo_calc->multiply( iv_a = 5 iv_b = 6 ).
WRITE: 'Sum:', lv_sum.
WRITE: / 'Product:', lv_product.
Why local classes are the right tool for prototyping
A local class exists because you defined it, so it needs no repository, no transport and no system. That also makes it the fix for one of the most common AI-generated ABAP failures: code that calls a plausible-sounding standard class which does not actually exist. Model the behaviour locally, verify the logic, and swap in the real class once you can confirm its name.