OOP ABAP
ABAP Developmentintermediate

OOP ABAP Part 6: Encapsulation and Visibility — PUBLIC, PROTECTED, PRIVATE

Key takeaway

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

  1. Run the code example; try to change mv_seatsocc directly from the report — syntax error.
  2. Read mv_carrid (READ-ONLY) from outside — allowed.
  3. 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

ABAP Code
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.

Practice more with Interview AI →

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

Interview questions on this topic

Related SAP topics