Appearance
Lesson 5 — Object APIs, Validation & Collaboration
Lesson 4 introduced encapsulated objects. This lesson focuses on designing their APIs so invalid state is difficult to create.
Learning objectives
- validate constructor input;
- maintain object invariants;
- distinguish meaningful mutation from generic setters;
- use private helper methods;
- pass objects to methods;
- create internal tables of object references;
- loop through objects and call methods;
- explain collaboration between objects.
1. Object invariants
An invariant is a rule that should remain true for a valid object.
For a Product:
text
code is not empty
name is not empty
stock >= 0Every public operation should preserve those rules.
2. Strengthen the constructor
Create:
text
ZCL_VALIDATED_PRODUCT_###Private state:
text
code
name
stock
low_stock_thresholdConstructor:
abap
METHODS constructor
IMPORTING
code TYPE c LENGTH 6
name TYPE string
initial_stock TYPE i
low_stock_threshold TYPE i DEFAULT 5.Implementation should normalize invalid numeric values rather than allowing negative stock/threshold into state.
3. Private helper method
Add:
abap
METHODS normalize_non_negative
IMPORTING value TYPE i
RETURNING VALUE(result) TYPE i.Put it in PRIVATE SECTION.
abap
METHOD normalize_non_negative.
IF value < 0.
result = 0.
ELSE.
result = value.
ENDIF.
ENDMETHOD.The helper supports the class implementation but is not part of the external API.
4. Controlled name change
A product name may legitimately change, so a method can represent that operation:
abap
METHODS rename
IMPORTING new_name TYPE string
RETURNING VALUE(changed) TYPE abap_bool.Only accept non-initial names.
5. Low stock as a query
Instead of storing a redundant Boolean flag, calculate it from state:
abap
METHODS is_low_stock
RETURNING VALUE(result) TYPE abap_bool.abap
METHOD is_low_stock.
result = xsdbool( stock <= low_stock_threshold ).
ENDMETHOD.xsdbool( ... ) converts a logical expression to the conventional ABAP Boolean representation.
Derived state does not need to be stored when it can be calculated reliably.
6. Object collaboration
Create a separate class:
text
ZCL_INVENTORY_###Its responsibility is to manage a collection of Product object references.
7. Define a reference type and table type
abap
TYPES ty_product_ref TYPE REF TO zcl_validated_product_###.
TYPES tt_products TYPE STANDARD TABLE OF ty_product_ref WITH EMPTY KEY.Private attribute:
abap
DATA products TYPE tt_products.8. Add a Product object
abap
METHODS add_product
IMPORTING product TYPE REF TO zcl_validated_product_###.Implementation:
abap
METHOD add_product.
APPEND product TO products.
ENDMETHOD.The Inventory stores references to Product objects, not copies of Product state.
9. Count low-stock products
abap
METHODS count_low_stock
RETURNING VALUE(count) TYPE i.abap
METHOD count_low_stock.
LOOP AT products INTO DATA(product).
IF product->is_low_stock( ) = abap_true.
count += 1.
ENDIF.
ENDLOOP.
ENDMETHOD.10. Collaboration diagram
text
Inventory object
│
├── reference → Product A
├── reference → Product B
└── reference → Product CThe Inventory asks each Product about its state through public methods.
It does not access Product private attributes.
11. Why references matter
If the Inventory holds a reference to the same Product object used elsewhere, both callers interact with the same object identity/state.
text
runner ───────┐
▼
Product object
▲
inventory ────┘12. Design rule: tell objects what to do
Prefer:
text
product->remove_stock( 3 )over:
text
get stock
calculate new stock outside
set stockThe first keeps the rule with the object that owns the state.
13. Summary
You now understand:
text
object invariants
validation
private helper methods
derived state
controlled mutation
object references
collections of object references
object collaborationLesson 6 introduces inheritance and reference typing.