SAP ABAP Classes
Classes bring object-oriented programming to ABAP. Modern ABAP is object-oriented, code is organised into classes with attributes and methods, and understanding OO ABAP is essential for writing clean, reusable, testable code.
An ABAP class bundles attributes and methods behind public and private sections, is instantiated with NEW, and is local to a program or global in SE24 or ADT. Inheritance and interfaces give reuse, static members belong to the class, and class-based exceptions under CX_ROOT replace SY-SUBRC checks. The payoff is ABAP Unit: a class can be tested.
- Watch out: Writing procedural code where OO would be cleaner/reusable.
Why object-oriented ABAP
OO ABAP replaces sprawling procedural programs with encapsulated classes: data (attributes) and behaviour (methods) bundled together, with clear interfaces and reuse through inheritance and interfaces. SAP’s modern frameworks (RAP, many APIs) are OO, and unit testing (ABAP Unit) works naturally with classes.
Local vs global classes
- Local classes: defined inside a program (DEFINITION/IMPLEMENTATION).
- Global classes: created in class builder (SE24) or ADT, reusable across the system.
A simple class
CLASS lcl_calculator DEFINITION.
PUBLIC SECTION.
METHODS add IMPORTING iv_a TYPE i iv_b TYPE i
RETURNING VALUE(rv_sum) TYPE i.
ENDCLASS.
CLASS lcl_calculator IMPLEMENTATION.
METHOD add.
rv_sum = iv_a + iv_b.
ENDMETHOD.
ENDCLASS.
DATA(lo_calc) = NEW lcl_calculator( ).
DATA(lv_result) = lo_calc->add( iv_a = 2 iv_b = 3 ).Key OO concepts
Learn encapsulation (public/private sections), instantiation (NEW), inheritance and interfaces, and static vs instance members. These enable clean, reusable designs and are expected in modern SAP development.
Two ABAP-specific details are worth adding because they come up immediately. Static components belong to the class rather than to an instance and are addressed with the class name and a double arrow; instance components use the object reference and a single arrow. And interfaces in ABAP are a separate object type, implemented by a class, which is how a program can work with anything that provides a given set of methods without knowing which class it is.
Exceptions, which are where OO ABAP pays off
Classic ABAP reported errors through SY-SUBRC, which every caller had to check and most
did not. Class-based exceptions replace that, and they are worth adopting even in otherwise procedural
code.
An exception is a class inheriting from CX_ROOT, through one of three branches.
CX_STATIC_CHECK must be declared and handled, and the compiler enforces it, which suits
errors a caller is expected to deal with. CX_DYNAMIC_CHECK is checked at runtime, for
conditions that should not happen if the caller did its job. CX_NO_CHECK is for the
unrecoverable, and it propagates without being declared anywhere.
A method declares what it raises with RAISING, and a caller handles it with
TRY, CATCH and optionally CLEANUP.
The gain is that an error carries information. An exception object holds a message, and often the
data that caused it, so the caller can report something useful rather than a return code. And an
unhandled exception produces a short dump naming the exception class, which is far more diagnosable than
a program that silently continued because nobody checked SY-SUBRC.
Convert a report into a class
An hour, and it is the exercise that makes the difference tangible rather than theoretical.
- Take a small procedural report with a few form routines and global variables.
- Create a local class in the same program. Move the data declarations into its private section.
- Turn each form routine into a method, public only where it is called from outside.
- Replace
SY-SUBRCchecks in one method with a raised exception, and handle it in the caller. - Try to access a private attribute from outside the class. The compiler refuses, which is encapsulation doing its job.
- Now move the class to a global class in
SE24or Eclipse and call it from a second program.
Step six is the payoff. The logic is now reusable and testable, and step five is why: nothing outside can reach into its state.
Testing, which is what this makes possible
The strongest practical argument for classes in ABAP is that they can be unit tested and procedural programs largely cannot.
ABAP Unit is built in. A local test class marked FOR TESTING holds methods that
instantiate the class under test, call it and assert the result. It runs from the editor, and it runs in
bulk across a package.
What makes a class testable is the same thing that makes it well designed: it takes its inputs as parameters rather than reading globals, and its dependencies can be replaced. A class that selects from the database inside its logic cannot be tested without that data existing; one that receives the data can be tested with anything.
That is why the discipline is worth adopting even in a landscape with no test culture. Code written this way is diagnosable and changeable, and code that is one long routine reading global state is neither. See internal tables and conditions for the constructs inside those methods.
When a class is not the answer
Object orientation is the default for new development and it is not universally right, and being able to say why is part of using it well.
A short report that selects and displays does not need a class hierarchy. Wrapping fifty lines in a class with one method adds ceremony and no benefit.
An enhancement or exit is called by the framework at a fixed point with fixed parameters. Structure inside it can still be a class, and the entry point is not yours to design.
A CDS view or an Open SQL statement does the job better where the requirement is reading and shaping data. Writing a class to loop over rows that a view could have aggregated is object-oriented code doing the wrong thing.
Existing procedural code that works and is rarely touched is not worth rewriting on principle. Refactoring earns its place when the code is about to change anyway.
The honest guidance: use classes where logic is reused, where it needs testing, or where the state is complex enough that keeping it private matters. Use the simplest thing that works elsewhere.
The patterns you will meet in delivered code
Reading SAP's own classes teaches the conventions faster than any guide, and a few patterns recur often enough to name.
Factory methods. A static method returning an instance, rather than the caller using
CREATE OBJECT directly. It lets the class decide which subclass to return and keeps
construction in one place.
Singletons. A class with one shared instance, obtained through a static
get_instance. Common for buffers and configuration readers, and worth using sparingly
because shared state is what testing struggles with.
Interfaces as contracts. A method taking an interface reference rather than a class reference, so any implementation can be passed. This is what makes substitution and testing possible.
Badis as objects. Enhancement points in modern code are interfaces with implementations found at runtime, which is the same idea applied to extensibility.
Recognising these makes standard code readable, and standard code is where most of the answers are when you are stuck. The habit worth building is opening the delivered class rather than searching for documentation about it.
Common pitfalls
- Writing procedural code where OO would be cleaner/reusable.
- Exposing everything public, breaking encapsulation.
- Ignoring ABAP Unit testing that OO enables.
- A class that is one enormous method. It is a form routine with a new syntax and none of the benefit.
- Everything public. Encapsulation is the point, and a class with no private section is a namespace.
- Catching
CX_ROOTand ignoring it. That is the modern equivalent of not checkingSY-SUBRC. See the class reference for the delivered classes worth knowing.
- Inheritance used where composition would do. Deep hierarchies are hard to follow and hard to change; a class holding another class is usually clearer.
Where this goes next
Writing a class is straightforward, and structuring one so it can be tested and reused across programs is the part you do in the course.
The test of whether a class is doing its job is whether you can write a unit test for it without a database. If you cannot, its logic and its data access are tangled together, and separating them is usually the improvement worth making.