OOP ABAP Part 10: OOP in S/4HANA, RAP and Clean Core
See where classic OOP knowledge is used in S/4HANA: BAdIs as interfaces, released APIs and wrapper classes, RAP behaviour pools with local handler classes, ABAP Cloud restrictions and Clean ABAP guidelines for classes.
Explanation
📌 KEY POINTS
✅ In S/4HANA, extensions are object-oriented: BAdIs are interfaces, RAP behaviour is implemented in classes, and released APIs are classes/interfaces.
✅ Clean core: use released objects (C1 contract) and wrap unreleased functionality in your own class when needed.
✅ RAP behaviour pools are global classes with local handler classes (lhc_…) and saver classes (lsc_…).
⚠️ In ABAP Cloud (language version 5), classic FORMs, WRITE lists, direct SAP table access and unreleased FMs are not allowed.
━━━━━━━━━━━━━━━━━━━━
▶ WHERE WE ARE
Parts 1–9 built OOP skills. This lesson connects them to what you meet in S/4HANA projects today — while classic ECC and on-premise code still runs in the same system.\n\n━━━━━━━━━━━━━━━━━━━━\n▶ 1. BAdIs = INTERFACES\nA new BAdI implementation (SE19/ADT) is a class implementing the BAdI interface (IF_EX_… classic, IF_BADI_… new). The framework instantiates it (GET BADI / CALL BADI). Everything from Part 3 and 8 applies: interfaces, factories, polymorphism.\n\n━━━━━━━━━━━━━━━━━━━━\n▶ 2. RELEASED APIs AND WRAPPERS\n• SAP marks objects as released (API state C1 for use in cloud development).
- In ABAP Cloud you may use only released CDS views, classes and interfaces (e.g. XCO library, CL_ABAP_CONTEXT_INFO instead of sy-uname in some cases).
- If you need unreleased functionality on-premise, create a wrapper class in a classic (standard ABAP) package, release it yourself for your cloud-ready code, and keep the dependency in one place.
━━━━━━━━━━━━━━━━━━━━
▶ 3. RAP BEHAVIOUR POOLS
- The behaviour definition points to a class ZBP_…; its global part is empty.
- Local classes inside it: lhc_booking INHERITING FROM cl_abap_behavior_handler with methods FOR VALIDATE, FOR DETERMINE, FOR MODIFY (actions); lsc_booking INHERITING FROM cl_abap_behavior_saver for save.
- Business logic can live in separate reusable classes called from the handlers — classic OOP design inside RAP.
━━━━━━━━━━━━━━━━━━━━
▶ 4. CLEAN ABAP FOR CLASSES
- Small classes with one responsibility; FINAL by default.
- Prefer instance methods and interfaces; inject dependencies.
- Raise exceptions, don't return error codes.
- Use meaningful names; avoid Hungarian prefixes overload (team decision).
- ATC with the cloud readiness / clean core checks.
━━━━━━━━━━━━━━━━━━━━
▶ 5. CLASSIC CODE IN S/4HANA ON-PREMISE
Existing reports, FORM-based exits and FMs still run. New code: classes; changed code: refactor step by step (move logic into classes, keep the old entry points). Tier model: tier 1 cloud-ready, tier 2 wrappers, tier 3 classic (to be reduced).
━━━━━━━━━━━━━━━━━━━━
▶ STEP BY STEP
- Open a RAP behaviour pool (ZBP_…) and identify lhc_ and lsc_ classes.
- Implement a BAdI and note the interface it implements.
- Create a wrapper class for an unreleased FM, as in the code example.
✅ CHECKPOINT: you can see where your OOP knowledge fits in S/4HANA extension and RAP development.
Code example
* ===== 1. Wrapper class (tier 2): encapsulate an unreleased FM behind an interface =====INTERFACE zif_material_reader PUBLIC. METHODS get_description IMPORTING iv_matnr TYPE matnr RETURNING VALUE(rv_text) TYPE maktx.ENDINTERFACE. CLASS zcl_material_reader DEFINITION PUBLIC FINAL CREATE PUBLIC. PUBLIC SECTION. INTERFACES zif_material_reader.ENDCLASS. CLASS zcl_material_reader IMPLEMENTATION. METHOD zif_material_reader~get_description. DATA ls_makt TYPE makt. CALL FUNCTION 'MAKT_SINGLE_READ' " classic, unreleased - kept in one place EXPORTING matnr = iv_matnr spras = sy-langu IMPORTING wmakt = ls_makt EXCEPTIONS OTHERS = 1. IF sy-subrc = 0. rv_text = ls_makt-maktx. ENDIF. ENDMETHOD.ENDCLASS.* Cloud-ready code uses only ZIF_MATERIAL_READER (released for use by the team). * ===== 2. RAP behaviour pool ZBP_I_FLIGHTBOOKING: local handler class =====CLASS lhc_booking DEFINITION INHERITING FROM cl_abap_behavior_handler. PRIVATE SECTION. METHODS validate_seats FOR VALIDATE ON SAVE IMPORTING keys FOR booking~validateSeats.ENDCLASS. CLASS lhc_booking IMPLEMENTATION. METHOD validate_seats. READ ENTITIES OF zi_flightbooking IN LOCAL MODE ENTITY booking FIELDS ( carrid connid fldate ) WITH CORRESPONDING #( keys ) RESULT DATA(lt_booking). LOOP AT lt_booking INTO DATA(ls_booking).* Reusable OO logic called from the handler IF zcl_flight_capacity=>get_instance( )->is_full( iv_carrid = ls_booking-carrid iv_connid = ls_booking-connid iv_fldate = ls_booking-fldate ) = abap_true. APPEND VALUE #( %tky = ls_booking-%tky ) TO failed-booking. APPEND VALUE #( %tky = ls_booking-%tky %msg = new_message( id = 'ZFLIGHT' number = '001' severity = if_abap_behv_message=>severity-error v1 = ls_booking-carrid v2 = ls_booking-connid ) ) TO reported-booking. ENDIF. ENDLOOP. ENDMETHOD.ENDCLASS. * ===== 3. Classic BAdI implementation = a class implementing an interface =====* CLASS zcl_im_me_process_po_cust DEFINITION PUBLIC FINAL CREATE PUBLIC.* PUBLIC SECTION.* INTERFACES if_ex_me_process_po_cust.* ENDCLASS.Real project scenario
During an S/4HANA conversion, a team wanted new approval logic to be cloud-ready, but it needed material texts read by an unreleased function module. Calling the FM directly would have failed the clean core ATC checks for the new package.
They created a wrapper class ZCL_MATERIAL_READER with an interface in a classic package and used only the interface in the new RAP-based approval logic. When SAP later released a CDS view for material texts, only the wrapper implementation changed.
Common mistakes
- Calling unreleased SAP objects directly from cloud-ready code.
- Putting all business logic inside RAP handler methods.
- Treating BAdI implementations as places for huge procedural code.
- Ignoring ATC clean core findings.
- Rewriting all classic code at once instead of step by step.
Best practices
- Use released APIs; wrap unreleased ones in a single class.
- Keep RAP handlers thin; call reusable classes.
- Apply Clean ABAP: small FINAL classes, interfaces, exceptions, DI.
- Run ATC with cloud readiness checks.
- Refactor classic code gradually behind stable entry points.
Interview angle
Questions: "How is OOP used in S/4HANA and RAP?", "What is a wrapper class in clean core?", "What is not allowed in ABAP Cloud?"
Strong answer: BAdIs are interfaces implemented by classes; RAP behaviour pools use local handler/saver classes inheriting from CL_ABAP_BEHAVIOR_HANDLER/SAVER; clean core uses released APIs, and unreleased functionality is wrapped in own classes (tier 2); ABAP Cloud forbids unreleased objects, WRITE lists, dynpros and direct SAP table access; business logic in reusable classes.
Practice this lesson
Quick check
1. In a RAP behaviour pool, where is validation logic implemented?
2. In a clean core approach, how should cloud-ready custom code use an unreleased SAP function module?
3. What is a BAdI implementation technically?
Interview questions
1. How do you evolve an ABAP monolith toward clean OO without a rewrite?
Answer it in your own words first, then compare.
2. A sales-order rule exists separately in a user exit, an OData service and a background job. How would you consolidate it in an S/4HANA clean core approach?
Answer it in your own words first, then compare.
Reference-verified: the steps are checked against official SAP documentation and tutorials, and object and field names in the sample code are checked for consistency. The code has not been compiled or run on an SAP system by ERPClimb. Syntax marked release-dependent varies by SAP release, so check it in your own system.
More lessons in this topic
- OOP ABAP Part 1: Classes, Objects, Attributes and Methods
- OOP ABAP Part 2: Local Classes vs Global Classes
- OOP ABAP Part 3: Inheritance, Interfaces and Polymorphism
- OOP ABAP Part 4: Class-Based Exceptions
- OOP ABAP Part 5: Instance Methods, Static Methods and Constructors
- OOP ABAP Part 6: Encapsulation and Visibility — PUBLIC, PROTECTED, PRIVATE
- OOP ABAP Part 7: Composition vs Inheritance
- OOP ABAP Part 8: Interfaces and Factory Methods