[ABAP] OO: Lokale Exception-Klasse anlegen, auslösen und behandeln

* lokale Exception-Klasse, erbt von cx_static_check
CLASS lcx_my_exception DEFINITION INHERITING FROM cx_static_check FINAL CREATE PUBLIC.
  PUBLIC SECTION.

* eigener Konstruktor mit zus. Parameter field_info
    METHODS: constructor
      IMPORTING
        !textid    LIKE textid OPTIONAL
        !previous  LIKE previous OPTIONAL
        field_info TYPE string OPTIONAL.

* neue Methode
    METHODS:
      get_fieldinfo
        RETURNING VALUE(re_field_info) TYPE string.

  PRIVATE SECTION.
    DATA: gv_field_info TYPE string.
ENDCLASS.

CLASS lcx_my_exception IMPLEMENTATION.
  METHOD constructor.
    super->constructor( textid = textid
                        previous = previous ).

    gv_field_info = field_info.
  ENDMETHOD.

  METHOD get_fieldinfo.
    re_field_info = gv_field_info.
  ENDMETHOD.
ENDCLASS.

CLASS lcl_demo DEFINITION.
  PUBLIC SECTION.
    CLASS-METHODS:
      div
        IMPORTING i_val1        TYPE f
                  i_val2        TYPE f
        RETURNING VALUE(rv_ret) TYPE f
* Propagieren der Exception
        RAISING   lcx_my_exception.
ENDCLASS.

CLASS lcl_demo IMPLEMENTATION.
  METHOD div.
    IF i_val2 = '0.0'.
* Wenn durch 0.0 geteilt werden soll: Auslösen der lokalen Exception, zusätzlichen Parameter übergeben
      RAISE EXCEPTION TYPE lcx_my_exception
        EXPORTING
          field_info = 'Neue Feldinfo.'.
    ELSE.
      rv_ret = i_val1 / i_val2.
    ENDIF.
  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
  TRY.
* durch 0.0 teilen -> Exception wird ausgelöst
      WRITE: / lcl_demo=>div( i_val1 = '1.1'
                              i_val2 = '0.0' ).
* Abfangen der lokalen Exception
    CATCH lcx_my_exception INTO DATA(e_txt).
      WRITE: / e_txt->get_text( ).
* zusätzlichen Parameter holen
      WRITE: / e_txt->get_fieldinfo( ).
  ENDTRY.

[ABAP] OO: Vererbung, Methodenredefinition, Vererbungshierarchie

* Einfache Klasse für Demo von Vererbung von Oberklasse an Unterklasse
* Methodenredefinition, Vererbungshierarchie

* Oberklasse
CLASS lcl_auto DEFINITION.
  PUBLIC SECTION.
* Instanzkonstruktor
    METHODS:
      constructor
        IMPORTING
          i_name TYPE string.

* funktionale Instanzmethode, gibt Namen zurück
    METHODS:
      get_name
        RETURNING VALUE(rv_name) TYPE string.

* funktionale Instanzmethode, gibt Ergebnis zurück
    METHODS:
      get_type_and_name
        RETURNING VALUE(rv_type_name) TYPE string.

  PROTECTED SECTION.
* funktionale Instanzmethode, ist nur innerhalb der Vererbungshierarchie sichtbar
    METHODS:
      get_type
        RETURNING VALUE(rv_type) TYPE string.

  PRIVATE SECTION.
    DATA: gv_name TYPE string.
ENDCLASS.

CLASS lcl_auto IMPLEMENTATION.
  METHOD constructor.
    gv_name = i_name.
  ENDMETHOD.

  METHOD get_name.
    rv_name = gv_name.
  ENDMETHOD.

  METHOD get_type_and_name.
* Aufruf der verdeckten Klassen-Funktion über me-> (kann auch weggelassen werden)
    rv_type_name = |{ me->get_type( ) }: { gv_name }|.
  ENDMETHOD.

  METHOD get_type.
    rv_type = 'AUTO'.
  ENDMETHOD.
ENDCLASS.

* Unterklasse lcl_kombi, erbt von lcl_auto
CLASS lcl_kombi DEFINITION INHERITING FROM lcl_auto.
  PROTECTED SECTION.
* Methode der Oberklasse wird überschrieben
    METHODS:
      get_type REDEFINITION.
ENDCLASS.

CLASS lcl_kombi IMPLEMENTATION.
  METHOD get_type.
* Aufruf der Funktion der Oberklasse über "super"
    rv_type = |{ super->get_type( ) } -> KOMBI|.
  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
* Kombi erzeugen
  DATA(o_kombi) = NEW lcl_kombi( 'Audi A3' ).
* Methode der Klasse lcl_auto auftrufen
  WRITE: / o_kombi->get_name( ).
* Methode der Klasse lcl_kombi auftrufen
  WRITE: / o_kombi->get_type_and_name( ).

[ABAP] OO: Vererbung, Polymorphie, Aggregation, CAST

* Einfache Klasse für Demo von Vererbung, Polymorphie und Casting (Up/Down) von Objektreferenzen

* Oberklasse
CLASS lcl_auto DEFINITION.
  PUBLIC SECTION.
    METHODS:
      constructor
        IMPORTING
          i_name TYPE string.

    METHODS:
      get_name
        RETURNING VALUE(rv_name) TYPE string.

  PRIVATE SECTION.
    DATA: gv_name TYPE string.
ENDCLASS.

CLASS lcl_auto IMPLEMENTATION.
  METHOD constructor.
    gv_name = i_name.
  ENDMETHOD.

  METHOD get_name.
    rv_name = gv_name.
  ENDMETHOD.
ENDCLASS.

* Unterklasse, erbt von lcl_auto
CLASS lcl_kombi DEFINITION INHERITING FROM lcl_auto.
  PUBLIC SECTION.
    METHODS:
* neue funktionale Methode
* gibt Stauraum des Kombis zurück
      get_space
        RETURNING VALUE(rv_room) TYPE i.
ENDCLASS.

CLASS lcl_kombi IMPLEMENTATION.
  METHOD get_space.
    rv_room = 3.
  ENDMETHOD.
ENDCLASS.

* Unterklasse, erbt von lcl_auto
CLASS lcl_limo DEFINITION INHERITING FROM lcl_auto.
  PUBLIC SECTION.
    METHODS:
* neue funktionale Methode
* gibt cw-Wert zurück
      get_cw
        RETURNING VALUE(rv_cw) TYPE f.
ENDCLASS.

CLASS lcl_limo IMPLEMENTATION.
  METHOD get_cw.
    rv_cw = '1.22'.
  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
* Aggregation: iTab mit Referenzen auf Autos
  DATA: it_cars TYPE STANDARD TABLE OF REF TO lcl_auto.

* verschiedene Autotypen erzeugen und in iTab ablegen
* impliziter Up-Cast (Widening-Cast) von lcl_kombi und lcl_limo -> lcl_auto
  APPEND NEW lcl_kombi( 'Audi A3' ) TO it_cars.
  APPEND NEW lcl_kombi( 'VW Passat' ) TO it_cars.
  APPEND NEW lcl_limo( 'Mercedes C' ) TO it_cars.
  APPEND NEW lcl_limo( 'Skoda Octavia' ) TO it_cars.

* Tabelle mit Autos durchgehen
  LOOP AT it_cars ASSIGNING FIELD-SYMBOL(<fs_car>).

* funktionale Methode von lcl_car aufrufen
    WRITE: / <fs_car>->get_name( ).

* spezielle Methoden der von lcl_auto abgeleiteten Unterklassen aufrufen
    TRY.
* probieren, ob sich das Auto zu einem Kombi casten lässt
* expliziter Down-Cast (Narrowing-Cast) von lcl_auto -> lcl_kombi
        DATA(o_kombi) = CAST lcl_kombi( <fs_car> ).
* Stauraum des Kombis ausgeben
        WRITE: / o_kombi->get_space( ), 'm³'.
      CATCH cx_sy_move_cast_error.
        WRITE: / 'Kein Kombi'.
    ENDTRY.

    TRY.
* probieren, ob sich das Auto zu einer Limo casten lässt
* expliziter Down-Cast (Narrowing-Cast) von lcl_auto -> lcl_limo
        DATA(o_limo) = CAST lcl_limo( <fs_car> ).
* cw-Wert der Limo ausgeben
        WRITE: / 'cw = ', o_limo->get_cw( ).
      CATCH cx_sy_move_cast_error.
        WRITE: / 'Keine Limo'.
    ENDTRY.

    ULINE.

  ENDLOOP.