ABAP Objects: Inheritance, Interfaces & Polymorphism
ABAP supports single inheritance; every class implicitly inherits from OBJECT.
21.1 Inheritance
ABAP supports single inheritance; every class implicitly inherits from OBJECT.
ABSTRACT classes can't be instantiated; abstract methods have no implementation.
FINAL classes can't be inherited from; FINAL methods can't be redefined.
Redefinition keeps the same signature (no overloading in ABAP).
CLASS lcl_shape DEFINITION ABSTRACT.
PUBLIC SECTION.
METHODS constructor IMPORTING iv_name TYPE string.
METHODS area ABSTRACT RETURNING VALUE(rv_area) TYPE f.
METHODS describe RETURNING VALUE(rv_text) TYPE string.
PROTECTED SECTION.
DATA mv_name TYPE string.
ENDCLASS.
CLASS lcl_shape IMPLEMENTATION.
METHOD constructor.
mv_name = iv_name.
ENDMETHOD.
METHOD describe.
rv_text = |{ mv_name } with area { area( ) DECIMALS = 2 }|.
ENDMETHOD.
ENDCLASS.
CLASS lcl_circle DEFINITION INHERITING FROM lcl_shape FINAL.
PUBLIC SECTION.
METHODS constructor IMPORTING iv_radius TYPE f.
METHODS area REDEFINITION.
PRIVATE SECTION.
DATA mv_radius TYPE f.
ENDCLASS.
CLASS lcl_circle IMPLEMENTATION.
METHOD constructor.
super->constructor( `Circle` ). " must call super constructor first
mv_radius = iv_radius.
ENDMETHOD.
METHOD area.
rv_area = '3.14159265' * mv_radius ** 2.
ENDMETHOD.
ENDCLASS.
CLASS lcl_rectangle DEFINITION INHERITING FROM lcl_shape.
PUBLIC SECTION.
METHODS constructor IMPORTING iv_w TYPE f iv_h TYPE f.
METHODS area REDEFINITION.
METHODS describe REDEFINITION.
PRIVATE SECTION.
DATA: mv_w
…21.2 Polymorphism
DATA lt_shapes TYPE STANDARD TABLE OF REF TO lcl_shape WITH EMPTY KEY.
lt_shapes = VALUE #( ( NEW lcl_circle( 2 ) ) ( NEW lcl_rectangle( iv_w = 3 iv_h = 4 ) ) ).
LOOP AT lt_shapes INTO DATA(lo_shape).
WRITE: / lo_shape->describe( ). " dynamic binding: subclass implementation runs
ENDLOOP.21.3 Interfaces
A class can implement many interfaces; interfaces can include other interfaces (INTERFACES lif_other. inside an interface).
Interface methods can be marked DEFAULT IGNORE / DEFAULT FAIL (7.51+) so implementers needn't implement them.
Implement partially in abstract classes with INTERFACES lif ABSTRACT METHODS m.
INTERFACE lif_printable.
CONSTANTS gc_version TYPE i VALUE 1.
METHODS print RETURNING VALUE(rv_text) TYPE string.
ENDINTERFACE.
INTERFACE lif_exportable.
METHODS to_json RETURNING VALUE(rv_json) TYPE string.
ENDINTERFACE.
CLASS lcl_invoice DEFINITION.
PUBLIC SECTION.
INTERFACES: lif_printable, lif_exportable.
ALIASES print FOR lif_printable~print.
ENDCLASS.
CLASS lcl_invoice IMPLEMENTATION.
METHOD lif_printable~print.
rv_text = `Invoice #42`.
ENDMETHOD.
METHOD lif_exportable~to_json.
rv_json = `{"id":42}`.
ENDMETHOD.
ENDCLASS.
DATA lo_printable TYPE REF TO lif_printable.
lo_printable = NEW lcl_invoice( ). " up-cast to interface
WRITE lo_printable->print( ).21.4 Casting
DATA lo_shape TYPE REF TO lcl_shape.
DATA lo_circle TYPE REF TO lcl_circle.
lo_shape = NEW lcl_circle( 1 ). " up-cast (widening): always allowed, implicit
lo_circle ?= lo_shape. " down-cast (narrowing), classic syntax
lo_circle = CAST #( lo_shape ). " modern syntax
IF lo_shape IS INSTANCE OF lcl_circle. " safe check (7.50+)
lo_circle = CAST #( lo_shape ).
ENDIF.
TRY.
DATA(lo_rect) = CAST lcl_rectangle( lo_shape ).
CATCH cx_sy_move_cast_error.
" wrong type
ENDTRY.21.5 Abstract vs interface
| | Abstract class | Interface | |-|----------------|-----------| | Implementation code | Yes (concrete methods) | No | | Attributes | Instance/static | Constants and (discouraged) attributes | | Multiple inheritance | No (one superclass) | A class implements many | | Use when | Sharing code among related classes | Defining contracts, enabling test doubles |