OOP ABAP Part 6: Encapsulation and Visibility — PUBLIC, PROTECTED, PRIVATE
Use visibility sections to protect object state: PUBLIC, PROTECTED and PRIVATE components, READ-ONLY attributes, getter/setter methods with validation, FRIENDS, and CREATE PRIVATE for controlled instantiation.
Explanation
📌 KEY POINTS
✅ PUBLIC: visible to everyone; PROTECTED: the class and its subclasses; PRIVATE: only the class itself (and friends).
✅ Encapsulation = keep data private and allow changes only through methods that validate them.
✅ READ-ONLY public attributes allow reading without allowing changes from outside.
⚠️ Public writable attributes let any program put an object into an invalid state.
━━━━━━━━━━━━━━━━━━━━
▶ WHERE WE ARE
Parts 1–5 used sections without much thought. Now we use them deliberately.
━━━━━━━━━━━━━━━━━━━━
▶ 1. THE THREE SECTIONS
- PUBLIC SECTION — the class's interface to the world. Everything here is a promise to callers; changing it can break them.
- PROTECTED SECTION — for subclasses: shared helpers and attributes they need.
- PRIVATE SECTION — implementation details. You can change them freely without affecting callers.
In SE24 the Visibility column shows Public/Protected/Private for each component.
━━━━━━━━━━━━━━━━━━━━
▶ 2. WHY ENCAPSULATE
Imagine seatsocc were public: any program could set it to 500 on a 200-seat flight. With a private attribute and a method book_seats( ), the class checks capacity every time. Business rules stay in one place.
━━━━━━━━━━━━━━━━━━━━
▶ 3. GETTERS, SETTERS AND READ-ONLY
- Getter: get_seatsocc( ) returns the value.
- Setter with validation: set_price( iv_price ) rejects negative prices.
- DATA mv_carrid TYPE s_carr_id READ-ONLY in the public section — readable from outside, changeable only inside the class. Useful for key attributes.
Don't create setters for everything — only for what callers are allowed to change.
━━━━━━━━━━━━━━━━━━━━
▶ 4. FRIENDS
CLASS lcl_flight DEFINITION FRIENDS ltc_flight_test. — the friend class can access private components. Mainly used for test classes; friendship is not inherited by friends' subclasses.
━━━━━━━━━━━━━━━━━━━━
▶ 5. CONTROLLED INSTANTIATION
- CREATE PUBLIC (default) — anyone can create objects.
- CREATE PROTECTED — only the class and subclasses.
- CREATE PRIVATE — only the class itself, e.g. through a static factory method or singleton (Part 8).
━━━━━━━━━━━━━━━━━━━━
▶ 6. FINAL
FINAL classes cannot be subclassed — this protects the design and makes changes to protected components safe.
━━━━━━━━━━━━━━━━━━━━
▶ STEP BY STEP
- Run the code example; try to change mv_seatsocc directly from the report — syntax error.
- Read mv_carrid (READ-ONLY) from outside — allowed.
- Call set_price with a negative value and see the exception.
✅ CHECKPOINT: your classes expose only what callers need and protect their state with validating methods.
Code example
REPORT zoop_visibility. CLASS lcl_flight DEFINITION CREATE PUBLIC. PUBLIC SECTION. DATA: mv_carrid TYPE s_carr_id READ-ONLY, " readable, not changeable outside mv_connid TYPE s_conn_id READ-ONLY. METHODS: constructor IMPORTING iv_carrid TYPE s_carr_id iv_connid TYPE s_conn_id iv_seatsmax TYPE i, book_seats IMPORTING iv_seats TYPE i RAISING zcx_flight_error, set_price IMPORTING iv_price TYPE s_price, get_seatsocc RETURNING VALUE(rv_occ) TYPE i, get_price RETURNING VALUE(rv_price) TYPE s_price. PROTECTED SECTION. DATA mv_seatsmax TYPE i. " subclasses may use it PRIVATE SECTION. DATA: mv_seatsocc TYPE i, " only via book_seats mv_price TYPE s_price. METHODS log_change IMPORTING iv_text TYPE string. " internal helperENDCLASS. CLASS lcl_flight IMPLEMENTATION. METHOD constructor. mv_carrid = iv_carrid. mv_connid = iv_connid. mv_seatsmax = iv_seatsmax. ENDMETHOD. METHOD book_seats. IF mv_seatsocc + iv_seats > mv_seatsmax. " the rule lives in ONE place RAISE EXCEPTION TYPE zcx_flight_error EXPORTING textid = zcx_flight_error=>flight_full mv_carrid = mv_carrid mv_connid = mv_connid. ENDIF. mv_seatsocc = mv_seatsocc + iv_seats. log_change( |{ iv_seats } seats booked| ). ENDMETHOD. METHOD set_price. IF iv_price < 0. RAISE EXCEPTION TYPE cx_parameter_invalid_range EXPORTING parameter = 'IV_PRICE'. " dynamic check: caller error ENDIF. mv_price = iv_price. ENDMETHOD. METHOD get_seatsocc. rv_occ = mv_seatsocc. ENDMETHOD. METHOD get_price. rv_price = mv_price. ENDMETHOD. METHOD log_change. WRITE: / mv_carrid, mv_connid, iv_text. ENDMETHOD.ENDCLASS. DATA: lo_flight TYPE REF TO lcl_flight, lv_occ TYPE i. START-OF-SELECTION. CREATE OBJECT lo_flight EXPORTING iv_carrid = 'LH' iv_connid = '0400' iv_seatsmax = 3. WRITE: / 'Carrier (read-only access):', lo_flight->mv_carrid.* lo_flight->mv_carrid = 'AA'. " syntax error: READ-ONLY* lo_flight->mv_seatsocc = 500. " syntax error: PRIVATE TRY. lo_flight->book_seats( 2 ). lo_flight->book_seats( 2 ). " exceeds capacity CATCH zcx_flight_error. WRITE: / 'Booking rejected: capacity exceeded'. ENDTRY. TRY. lo_flight->set_price( '-10' ). CATCH cx_parameter_invalid_range. WRITE: / 'Negative price rejected'. ENDTRY. lv_occ = lo_flight->get_seatsocc( ). WRITE: / 'Seats occupied:', lv_occ. * Test class access to private data:* CLASS lcl_flight DEFINITION FRIENDS ltc_flight_test.Real project scenario
A global class for sales order simulation had its item table as a public writable attribute. Two different enhancements modified the table directly, one of them without recalculating totals, and orders were saved with inconsistent header values.
The team made the table private, added methods add_item and remove_item that recalculate totals, and exposed a read-only copy via get_items. The next enhancement had to use the methods, and the inconsistency disappeared.
Common mistakes
- Public writable attributes.
- Setters without validation for every attribute.
- Putting internal helpers into the public section.
- Using PROTECTED as "almost private" in classes nobody inherits from.
- Overusing FRIENDS outside test classes.
Best practices
- Keep attributes private; expose behaviour, not data.
- Use READ-ONLY for key attributes callers need to read.
- Validate in setters and business methods.
- Mark classes FINAL unless inheritance is planned.
- Keep the public section small and stable.
Interview angle
Questions: "Explain encapsulation in ABAP", "PUBLIC vs PROTECTED vs PRIVATE?", "What is READ-ONLY?", "What are friends?"
Strong answer: visibility sections control access — public for everyone, protected for subclasses, private for the class (and friends); encapsulation keeps state private and changes it only through validating methods; READ-ONLY attributes are readable but not writable outside; FRIENDS grant private access (mainly tests); CREATE PRIVATE controls instantiation.
Practice this lesson
Quick check
1. What does READ-ONLY on a public attribute mean?
2. A document status must only change through valid transitions. Which design enforces this?
3. Which visibility allows access only from the class itself and its subclasses?
Interview questions
1. A custom document class exposes its status as a public attribute, and different programs set invalid status values. How do you fix this with encapsulation?
Answer it in your own words first, then compare.
2. Explain visibility modifiers (PUBLIC, PROTECTED, PRIVATE) in ABAP OO. How do they enforce encapsulation, and what is the impact on inheritance hierarchies?
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 10: OOP in S/4HANA, RAP and Clean Core
- 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 7: Composition vs Inheritance
- OOP ABAP Part 8: Interfaces and Factory Methods