ABAP Enumerations: Type-Safe Enumerated Types

Category
ABAP-Statements
Published
Author
Johannes

Enumerations are type-safe constants that define a fixed set of values. They replace loose CONSTANTS and provide compiler checking, better readability and maintainability.

Syntax

TYPES: BEGIN OF ENUM <enum_name> [ BASE TYPE <base_type> ] [ STRUCTURE <structure_name> ],
<value1> [ VALUE <n> ],
<value2> [ VALUE <n> ],
...
END OF ENUM <enum_name> [ STRUCTURE <structure_name> ].

Basic Principle

  • Enumerations define a closed set of values
  • Each value automatically gets an integer value (0, 1, 2, …)
  • Variables of enum type can only hold valid values
  • Compiler checking prevents invalid assignments

Examples

1. Simple Enumeration

" Define enumeration
TYPES: BEGIN OF ENUM ty_traffic_light,
red,
yellow,
green,
END OF ENUM ty_traffic_light.
" Declare variable
DATA: lv_light TYPE ty_traffic_light.
" Assign value
lv_light = red.
" Use in conditions
CASE lv_light.
WHEN red.
WRITE: / 'Stop!'.
WHEN yellow.
WRITE: / 'Caution!'.
WHEN green.
WRITE: / 'Go!'.
ENDCASE.

2. Comparison: Enumeration vs. Constants

" === OLD: Loose constants (error-prone) ===
CONSTANTS: c_status_new TYPE c VALUE 'N',
c_status_approved TYPE c VALUE 'A',
c_status_rejected TYPE c VALUE 'R'.
DATA: lv_status TYPE c.
lv_status = 'X'. " Invalid value - no compiler error!
" === NEW: Enumeration (type-safe) ===
TYPES: BEGIN OF ENUM ty_status,
new,
approved,
rejected,
END OF ENUM ty_status.
DATA: lv_status2 TYPE ty_status.
lv_status2 = approved. " OK
" lv_status2 = 'X'. " SYNTAX ERROR! Only enum values allowed

3. Enumeration with STRUCTURE

" With STRUCTURE for qualified access
TYPES: BEGIN OF ENUM ty_order_status STRUCTURE order_status,
open,
processing,
shipped,
delivered,
cancelled,
END OF ENUM ty_order_status STRUCTURE order_status.
DATA: lv_status TYPE ty_order_status.
" Qualified access via structure
lv_status = order_status-processing.
CASE lv_status.
WHEN order_status-open.
WRITE: / 'Order open'.
WHEN order_status-processing.
WRITE: / 'In processing'.
WHEN order_status-shipped.
WRITE: / 'Shipped'.
WHEN order_status-delivered.
WRITE: / 'Delivered'.
WHEN order_status-cancelled.
WRITE: / 'Cancelled'.
ENDCASE.

4. Explicit Values

" Default: Automatic values 0, 1, 2, ...
TYPES: BEGIN OF ENUM ty_auto,
val_a, " = 0
val_b, " = 1
val_c, " = 2
END OF ENUM ty_auto.
" Assign explicit values
TYPES: BEGIN OF ENUM ty_http_status STRUCTURE http_status BASE TYPE i,
ok VALUE 200,
created VALUE 201,
bad_request VALUE 400,
unauthorized VALUE 401,
not_found VALUE 404,
server_error VALUE 500,
END OF ENUM ty_http_status STRUCTURE http_status.
DATA: lv_http TYPE ty_http_status.
lv_http = http_status-not_found.
WRITE: / 'HTTP Status:', CONV i( lv_http ). " 404

5. BASE TYPE

" String-based enumeration
TYPES: BEGIN OF ENUM ty_color STRUCTURE color BASE TYPE string,
red VALUE `#FF0000`,
green VALUE `#00FF00`,
blue VALUE `#0000FF`,
white VALUE `#FFFFFF`,
black VALUE `#000000`,
END OF ENUM ty_color STRUCTURE color.
DATA: lv_color TYPE ty_color.
lv_color = color-blue.
" Extract value
DATA(lv_hex) = CONV string( lv_color ).
WRITE: / 'Color code:', lv_hex. " #0000FF

6. Enumeration in Classes

CLASS lcl_order DEFINITION.
PUBLIC SECTION.
" Enumeration as class type
TYPES: BEGIN OF ENUM ty_status STRUCTURE status,
draft,
submitted,
approved,
rejected,
END OF ENUM ty_status STRUCTURE status.
METHODS: constructor,
set_status IMPORTING iv_status TYPE ty_status,
get_status RETURNING VALUE(rv_status) TYPE ty_status,
approve,
reject.
PRIVATE SECTION.
DATA: mv_status TYPE ty_status.
ENDCLASS.
CLASS lcl_order IMPLEMENTATION.
METHOD constructor.
mv_status = status-draft.
ENDMETHOD.
METHOD set_status.
mv_status = iv_status.
ENDMETHOD.
METHOD get_status.
rv_status = mv_status.
ENDMETHOD.
METHOD approve.
IF mv_status = status-submitted.
mv_status = status-approved.
ENDIF.
ENDMETHOD.
METHOD reject.
IF mv_status = status-submitted.
mv_status = status-rejected.
ENDIF.
ENDMETHOD.
ENDCLASS.
" Usage
DATA(lo_order) = NEW lcl_order( ).
lo_order->set_status( lcl_order=>status-submitted ).
lo_order->approve( ).
DATA(lv_current) = lo_order->get_status( ).
IF lv_current = lcl_order=>status-approved.
WRITE: / 'Order approved'.
ENDIF.

7. Enumeration in SWITCH/COND

TYPES: BEGIN OF ENUM ty_weekday STRUCTURE weekday,
monday,
tuesday,
wednesday,
thursday,
friday,
saturday,
sunday,
END OF ENUM ty_weekday STRUCTURE weekday.
DATA: lv_day TYPE ty_weekday VALUE weekday-friday.
" With SWITCH
DATA(lv_type) = SWITCH string( lv_day
WHEN weekday-saturday OR weekday-sunday THEN 'Weekend'
ELSE 'Weekday'
).
" With COND
DATA(lv_message) = COND string(
WHEN lv_day = weekday-monday THEN 'Start of week'
WHEN lv_day = weekday-friday THEN 'Almost weekend!'
WHEN lv_day = weekday-saturday OR lv_day = weekday-sunday THEN 'Free!'
ELSE 'Normal day'
).
WRITE: / lv_type. " Weekday
WRITE: / lv_message. " Almost weekend!

8. Enumeration with VALUE

TYPES: BEGIN OF ENUM ty_priority STRUCTURE priority,
low,
medium,
high,
critical,
END OF ENUM ty_priority STRUCTURE priority.
TYPES: BEGIN OF ty_task,
id TYPE i,
name TYPE string,
priority TYPE ty_priority,
END OF ty_task.
" Initialize structure with enumeration
DATA(ls_task) = VALUE ty_task(
id = 1
name = 'Important task'
priority = priority-high
).
" Table with enumerations
DATA: lt_tasks TYPE TABLE OF ty_task.
lt_tasks = VALUE #(
( id = 1 name = 'Bug Fix' priority = priority-critical )
( id = 2 name = 'Feature' priority = priority-medium )
( id = 3 name = 'Docs' priority = priority-low )
).
" Filter by priority
LOOP AT lt_tasks INTO DATA(ls_t) WHERE priority >= priority-high.
WRITE: / ls_t-id, ls_t-name.
ENDLOOP.

9. Iterate Enum Values

TYPES: BEGIN OF ENUM ty_size STRUCTURE size,
xs,
s,
m,
l,
xl,
xxl,
END OF ENUM ty_size STRUCTURE size.
" Loop through all values (with integer conversion)
DO.
DATA(lv_size) = CONV ty_size( sy-index - 1 ).
" Check if valid value (within range)
IF lv_size > size-xxl.
EXIT.
ENDIF.
WRITE: / 'Size:', lv_size.
ENDDO.

10. Enumeration in Interfaces

INTERFACE lif_document.
TYPES: BEGIN OF ENUM ty_doc_type STRUCTURE doc_type,
invoice,
credit_memo,
delivery_note,
quotation,
END OF ENUM ty_doc_type STRUCTURE doc_type.
METHODS: get_type RETURNING VALUE(rv_type) TYPE ty_doc_type.
ENDINTERFACE.
CLASS lcl_invoice DEFINITION.
PUBLIC SECTION.
INTERFACES: lif_document.
ENDCLASS.
CLASS lcl_invoice IMPLEMENTATION.
METHOD lif_document~get_type.
rv_type = lif_document=>doc_type-invoice.
ENDMETHOD.
ENDCLASS.

11. Convert Enum to String

TYPES: BEGIN OF ENUM ty_payment STRUCTURE payment,
cash,
credit_card,
bank_transfer,
paypal,
END OF ENUM ty_payment STRUCTURE payment.
DATA: lv_payment TYPE ty_payment VALUE payment-credit_card.
" Enum name as string (Reflection)
DATA(lo_type) = CAST cl_abap_enumdescr(
cl_abap_typedescr=>describe_by_data( lv_payment )
).
" All members with names
LOOP AT lo_type->members INTO DATA(ls_member).
WRITE: / ls_member-name, '=', ls_member-value.
ENDLOOP.
" Output:
" CASH = 0
" CREDIT_CARD = 1
" BANK_TRANSFER = 2
" PAYPAL = 3

12. Practical Example: State Machine

CLASS lcl_document_workflow DEFINITION.
PUBLIC SECTION.
TYPES: BEGIN OF ENUM ty_state STRUCTURE state,
draft,
pending_review,
approved,
published,
archived,
END OF ENUM ty_state STRUCTURE state.
METHODS: constructor,
submit RETURNING VALUE(rv_success) TYPE abap_bool,
approve RETURNING VALUE(rv_success) TYPE abap_bool,
publish RETURNING VALUE(rv_success) TYPE abap_bool,
archive RETURNING VALUE(rv_success) TYPE abap_bool,
get_state RETURNING VALUE(rv_state) TYPE ty_state,
get_available_actions RETURNING VALUE(rt_actions) TYPE string_table.
PRIVATE SECTION.
DATA: mv_state TYPE ty_state.
ENDCLASS.
CLASS lcl_document_workflow IMPLEMENTATION.
METHOD constructor.
mv_state = state-draft.
ENDMETHOD.
METHOD submit.
IF mv_state = state-draft.
mv_state = state-pending_review.
rv_success = abap_true.
ENDIF.
ENDMETHOD.
METHOD approve.
IF mv_state = state-pending_review.
mv_state = state-approved.
rv_success = abap_true.
ENDIF.
ENDMETHOD.
METHOD publish.
IF mv_state = state-approved.
mv_state = state-published.
rv_success = abap_true.
ENDIF.
ENDMETHOD.
METHOD archive.
IF mv_state = state-published.
mv_state = state-archived.
rv_success = abap_true.
ENDIF.
ENDMETHOD.
METHOD get_state.
rv_state = mv_state.
ENDMETHOD.
METHOD get_available_actions.
rt_actions = SWITCH #( mv_state
WHEN state-draft THEN VALUE #( ( `Submit` ) )
WHEN state-pending_review THEN VALUE #( ( `Approve` ) ( `Reject` ) )
WHEN state-approved THEN VALUE #( ( `Publish` ) )
WHEN state-published THEN VALUE #( ( `Archive` ) )
ELSE VALUE #( )
).
ENDMETHOD.
ENDCLASS.

Enum vs. Domain vs. Constants

AspectEnumerationDomainConstants
Type safetyYes (Compiler)Yes (DDIC)No
ScopeLocal or GlobalGlobal (DDIC)Local or Global
Value checkCompile-timeRuntimeNone
TextsManualValue tableNone
Use caseModern logicDB fieldsLegacy code

Important Notes / Best Practice

  • Use STRUCTURE for qualified access (status-approved instead of just approved).
  • Enumerations are type-safe – invalid values lead to syntax errors.
  • BASE TYPE for non-integer-based enumerations (e.g., String).
  • Explicit VALUE only when needed (e.g., HTTP status codes, mapping to external values).
  • Enumerations replace loose constants for better maintainability.
  • cl_abap_enumdescr for reflection (reading names).
  • Combine with SWITCH and CASE for clean branching.
  • Enumerations can be defined in CLASS and INTERFACE.
  • Comparisons with =, <>, <, > are possible (based on ordinal value).
  • Ideal for state machines, status fields and configurable options.