[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.

[ABAP] OO: Implementation einer Factory-Klasse, Methodenverkettung (Method-Chaining)

* Einfache Klasse für Demo einer Factory-Klasse

* ist nicht über den Kontruktor von außen instanziierbar (CREATE PRIVATE), kann nur sich selbst instanziieren
* von lcl_factorydemo kann nicht geerbt werden (FINAL)
CLASS lcl_factorydemo DEFINITION FINAL CREATE PRIVATE.
  PUBLIC SECTION.
* statische Factory-Methode, übernimmt die Funktion des Konstruktors mit einigen organisatorischen Verbesserungen
    CLASS-METHODS:
      factory
        IMPORTING
                  i_object_name      TYPE string
        RETURNING VALUE(ro_instance) TYPE REF TO lcl_factorydemo.

* statische Methode, zeigt die interne sortierte Objektliste
    CLASS-METHODS:
      get_object_list.

* Instanzmethode, gibt Objektnamen
    METHODS:
      get_name
        RETURNING VALUE(rv_object_name) TYPE string.

  PRIVATE SECTION.
* eigener Listtyp zur Verwaltung der internen Objektreferenzen
* über "name" können die Objektreferenzen gesucht werden
    TYPES: BEGIN OF ty_instances,
             name       TYPE        string,
             o_instance TYPE REF TO lcl_factorydemo,
           END OF ty_instances.

* sortierte Liste zur Verwaltung der Objektreferenzen, Primärschlüssel ist "name"
    CLASS-DATA: git_instances TYPE SORTED TABLE OF ty_instances WITH UNIQUE KEY name.

* Instanzvariable, speichert Objektnamen
    DATA: gv_object_name TYPE string.

* versteckter Instanzkonstruktor, ist von außerhalb der Klasse nicht aufrufbar (CREATE PRIVATE)
    METHODS:
      constructor
        IMPORTING
          i_object_name TYPE string.
ENDCLASS.

CLASS lcl_factorydemo IMPLEMENTATION.
* versteckter Instanzkonstruktor, ist von außerhalb der Klasse nicht aufrufbar (CREATE PRIVATE)
  METHOD constructor.
    gv_object_name = i_object_name.
  ENDMETHOD.

* statische Factory-Methode
  METHOD factory.
    TRY.
* Instanz über den Namen suchen, wenn nicht vorhanden wird eine Exception CX_SY_ITAB_LINE_NOT_FOUND geworfen
        ro_instance = git_instances[ name = i_object_name ]-o_instance.
      CATCH cx_sy_itab_line_not_found.
* wenn also das Objekt nicht vorhanden ist, dann neues erzeugen
        ro_instance = NEW #( i_object_name ).
* und in die iTab eintragen, wird automatisch anhand des Namens einsortiert
        INSERT VALUE #( name = i_object_name
                        o_instance = ro_instance ) INTO TABLE git_instances.
    ENDTRY.
  ENDMETHOD.
* Instanzmethode, gibt Objektnamen
  METHOD get_name.
    rv_object_name = gv_object_name.
  ENDMETHOD.
* statische Methode, zeigt die interne sortierte Objektliste
  METHOD get_object_list.
    LOOP AT git_instances ASSIGNING FIELD-SYMBOL(<fs_inst>).
      WRITE: / <fs_inst>-name.
    ENDLOOP.
  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
* Drei Objekte per Factory-Methode erzeugen
* die ersten zwei Objekte werden erzeugt, da die Namen noch nicht
* in der internen Liste vorhanden sind
* die Objekte werden automatisch nach Namen sortiert (SORTED TABLE)
  DATA(o_ref1) = lcl_factorydemo=>factory( i_object_name = 'OBJ_2' ).
  WRITE: / o_ref1->get_name( ).

* Beispiel für Methodenverkettung (Method-Chaining)
  WRITE: / lcl_factorydemo=>factory( i_object_name = 'OBJ_1' )->get_name( ).

* das dritte Objekt wird nicht erzeugt, da schon ein Objekt mit dem gleichen Namen existiert
* daher wird nur die Referenz auf das namensgleiche Objekt zurückgegeben
  DATA(o_ref3) = lcl_factorydemo=>factory( i_object_name = 'OBJ_1' ).
  WRITE: / o_ref3->get_name( ).

  ULINE.

* sortierte Objektliste ausgeben -> nur zwei Objekte
* mit unterschiedlichen Namen werden angezeigt
  lcl_factorydemo=>get_object_list( ).

[ABAP] OO: Objektreferenzen in einer Liste verwalten, Objektsuche über Namen

* Demoklasse für Objekte, welche in einer sortierten Liste verwaltet werden
CLASS lcl_demo 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_demo IMPLEMENTATION.
  METHOD constructor.
    gv_name = i_name.
  ENDMETHOD.

  METHOD get_name.
    rv_name = gv_name.
  ENDMETHOD.
ENDCLASS.

* Listtyp zur Verwaltung der internen Objektreferenzen
* über "name" können die Objektreferenzen gesucht werden
TYPES: BEGIN OF ty_instances,
         name       TYPE        string,
         o_instance TYPE REF TO lcl_demo,
       END OF ty_instances.

* sortierte Liste zur Verwaltung der Objektreferenzen, Primärschlüssel ist "name"
DATA: it_instances TYPE SORTED TABLE OF ty_instances WITH UNIQUE KEY name.

START-OF-SELECTION.
* Objekte generieren und in die iTab einfügen
* iTab wird automatisch anhand der Spalte "name" sortiert
  INSERT VALUE #( name = 'REF2'
                  o_instance = NEW #( 'Udo' ) ) INTO TABLE it_instances.

  INSERT VALUE #( name = 'REF1'
                  o_instance = NEW #( 'Heinz' ) ) INTO TABLE it_instances.

  INSERT VALUE #( name = 'REF4'
                  o_instance = NEW #( 'Horst' ) ) INTO TABLE it_instances.

  INSERT VALUE #( name = 'REF3'
                  o_instance = NEW #( 'Rainer' ) ) INTO TABLE it_instances.

* Objekt anhand eines Namens suchen
  DATA(o_ref) = it_instances[ name = 'REF1' ]-o_instance.
  WRITE: / o_ref->get_name( ).

* sortierte Objektliste ausgeben
  LOOP AT it_instances ASSIGNING FIELD-SYMBOL(<fs_inst>).
    WRITE: / <fs_inst>-name, <fs_inst>-o_instance->get_name( ).
  ENDLOOP.

[ABAP] OO: Interfacedefinition, Generalisierung, Spezialisierung

* Einfache Klassen für Demo für Verwendung von Interfaces
* Über Interfaces kann im ABAP Mehrfachvererbung (Polymorphie) realisiert werden

* Interface, dient als Schablone, ohne Implementierungen
INTERFACE lif_auto.
  METHODS:
* Interface-Methode, liefert Fahrtrichtung
    get_direction
      RETURNING VALUE(rv_direction) TYPE string.
ENDINTERFACE.

* Klasse Kombi, spezialisert das Interface lif_auto
CLASS lcl_kombi DEFINITION.
  PUBLIC SECTION.
* Implementiert das Interface lif_auto
    INTERFACES:
      lif_auto.

* ALias-Namen als Vereinfachung für Zugriff definieren
    ALIASES:
      get_direction FOR lif_auto~get_direction.

    METHODS:
      get_name
        RETURNING VALUE(rv_name) TYPE string.
ENDCLASS.

CLASS lcl_kombi IMPLEMENTATION.
* Implementierung der Interface-Methode, liefert Fahrtrichtung
  METHOD lif_auto~get_direction.
    rv_direction = 'Berlin'.
  ENDMETHOD.
* Instanzmethode, liefert Namen
  METHOD get_name.
    rv_name = 'Opel'.
  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
* Objekt der Klasse Kombi + Funktionsaufruf
  DATA(o_ref) = NEW lcl_kombi( ).
* Aufruf der Instanzmethode
  WRITE: / 'Name:', o_ref->get_name( ).
* Aufruf der Interfacemethode allgemein
  WRITE: / 'Direction:', o_ref->lif_auto~get_direction( ).
* Aufruf der Interfacemethode über Alias-Namen (ALIASES)
  WRITE: / 'Direction:', o_ref->get_direction( ).

[ABAP] OO: Statischer Konstruktor, Instanzkonstruktor, statischer und dynamischer Methodenaufruf

* Einfache Klasse für Demo des statischen Konstruktors und des Instanzkonstruktors
* sowie eines statischen und dynamischen Methodenaufrufs
CLASS lcl_demo DEFINITION.
  PUBLIC SECTION.
* Instanzkonstruktor
    METHODS:
      constructor.

* funktionale Instanzmethode, gibt Ergebnis zurück
    METHODS:
      add
        IMPORTING
                  i_var1        TYPE i
                  i_var2        TYPE i
        RETURNING VALUE(rv_erg) TYPE i.

    CLASS-METHODS:
* statischer Konstruktor
      class_constructor.

* statische funktionale Methode, gibt Ergebnis zurück
    CLASS-METHODS:
      mul
        IMPORTING
                  i_var1        TYPE i
                  i_var2        TYPE i
        RETURNING VALUE(rv_erg) TYPE i.
ENDCLASS.

CLASS lcl_demo IMPLEMENTATION.
  METHOD class_constructor.
    WRITE: / 'statischer Konstruktor'.
  ENDMETHOD.

  METHOD constructor.
    WRITE: / 'dynamischer Konstruktor'.
  ENDMETHOD.

  METHOD add.
    rv_erg = i_var1 + i_var2.
  ENDMETHOD.

  METHOD mul.
    rv_erg = i_var1 * i_var2.
  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.

* erster Aufruf einer Methode der Klasse lcl_demo durch den Aufruf von mul( )
* -> ruft den Klassenkonstruktor, danach erst wird mul( ) statisch prozessiert
  WRITE: / lcl_demo=>mul( i_var1 = 4 i_var2 = 3 ).

* Objekt der Klasse lcl_demo erzeugen
  DATA(o_ref) = NEW lcl_demo( ).
* Methode add( ) aurufen
  WRITE: / o_ref->add( i_var1 = 2 i_var2 = 3 ).
* Methode mul( ) dynamisch prozessieren
  WRITE: / o_ref->mul( i_var1 = 2 i_var2 = 3 ).

[ABAP] OO: Instanzkonstruktor, funktionale Instanzmethode, Exceptionhandling

* Einfache Klasse für Demo des Konstruktors, Instanzmethode, Exceptionhandling
CLASS lcl_demo DEFINITION.
  PUBLIC SECTION.
* Instanzkonstruktor mit Übergabeparameter
* Propagiert Exception vom Typ cx_sy_create_object_error
    METHODS:
      constructor
        IMPORTING
          i_name TYPE string
        RAISING
          cx_sy_create_object_error.

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

  PRIVATE SECTION.
* globale, private Variable zur Speicherung des Namens
    DATA: gv_name TYPE string.
ENDCLASS.

CLASS lcl_demo IMPLEMENTATION.
  METHOD constructor.
* prüfen, ob Name leer
    IF i_name = ''.
* Exception werfen
      RAISE EXCEPTION TYPE cx_sy_create_object_error.
    ELSE.
      gv_name = i_name.
    ENDIF.
  ENDMETHOD.

  METHOD get_name.
* Namen zurückgeben
    rv_name = gv_name.
  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
* Exception provozieren
  TRY.
      DATA(o_ref) = NEW lcl_demo( i_name = '' ).

      WRITE: / o_ref->get_name( ).

    CATCH cx_sy_create_object_error INTO DATA(e_txt).
      WRITE: / e_txt->get_text( ).
  ENDTRY.
  
* "normale" Abarbeitung
  TRY.
      DATA(o_ref) = NEW lcl_demo( i_name = 'Test' ).

      WRITE: / o_ref->get_name( ).

    CATCH cx_sy_create_object_error INTO DATA(e_txt).
      WRITE: / e_txt->get_text( ).
  ENDTRY.

[ABAP] OO: Implementation einer Singleton-Klasse

* Singleton-Klasse, kann durch den Zusatz CREATE PRIVATE nur sich selbst instanziieren
* stellt einen Spezialfall einer Factory-Klasse dar
CLASS lcl_singleton DEFINITION CREATE PRIVATE.
  PUBLIC SECTION.
* Statischer Konstruktor, wird nur einmal aufgerufen
* erzeugt genau eine Referenz auf Singleton-Objekt
    CLASS-METHODS:
      class_constructor.

* Factory-Methode -> Gibt immer die gleiche Referenz auf Singleton-Objekt zurück
    CLASS-METHODS:
      get_instance RETURNING VALUE(ret_singleton) TYPE REF TO lcl_singleton.

* Testmethode, gibt eine GUID zurück
    METHODS:
      get_guid RETURNING VALUE(ret_guid) TYPE sysuuid_c32.

  PRIVATE SECTION.
* Referenz auf Singleton-Objekt
    CLASS-DATA: o_singleton TYPE REF TO lcl_singleton.
ENDCLASS.

CLASS lcl_singleton IMPLEMENTATION.
* Statischer Konstruktor, wird nur einmal aufgerufen
* erzeugt genau eine Referenz auf Singleton-Objekt
  METHOD class_constructor.
    o_singleton = NEW #( ).
  ENDMETHOD.

* Factory-Methode -> Gibt immer die gleiche Referenz auf Singleton-Objekt zurück
  METHOD get_instance.
    ret_singleton = o_singleton.
  ENDMETHOD.

* Testmethode, gibt eine GUID zurück
  METHOD get_guid.
    TRY.
        ret_guid = cl_system_uuid=>create_uuid_c32_static( ).
      CATCH cx_root.
    ENDTRY.
  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
  DATA(o_ref) = lcl_singleton=>get_instance( ).

  WRITE: / |{ o_ref->get_guid( ) }|.

[ABAP] OO: Events auslösen, Eventhandling

* Demo-Objekt, welches ein Event definiert und auslöst
CLASS lcl_demo DEFINITION.
  PUBLIC SECTION.
* der Event, der getriggert werden soll
    EVENTS:
      my_event
        EXPORTING
          VALUE(txt) TYPE string
          VALUE(val) TYPE i.

* Instanzkonstruktor mit Übergabeparameter
    METHODS:
      constructor
        IMPORTING
          iv_name TYPE string.

* die Methode, die den Event auslöst
    METHODS: write.

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

* Variable zum Speichern des Namens
  PRIVATE SECTION.
    DATA: gv_name TYPE string.
ENDCLASS.

CLASS lcl_demo IMPLEMENTATION.
* Instanzkonstruktor mit Übergabeparameter
  METHOD constructor.
    gv_name = iv_name.
  ENDMETHOD.
* die Methode, die den Event auslöst
  METHOD write.
    WRITE: / '1. lcl_demo triggert Event "my_event"'.
* Event auslösen
    RAISE EVENT my_event
      EXPORTING
        txt = 'Übergabetext'
        val = 1.
  ENDMETHOD.
* gibt Namen zurück
  METHOD get_name.
    rv_name = gv_name.
  ENDMETHOD.
ENDCLASS.

* Eventhandlerklasse, die Methoden zur Ereignisbehalndlung abbildet
CLASS lcl_eventhandler DEFINITION.
  PUBLIC SECTION.
* die Ereignisbehandlungsroutine, die mit dem Event über SET HANDLER verknüpft wird
    CLASS-METHODS: on_my_event FOR EVENT my_event OF lcl_demo
      IMPORTING
          txt
          val
          sender.
ENDCLASS.

CLASS lcl_eventhandler IMPLEMENTATION.
* die Ereignisbehandlungsroutine, die mit dem Event verknüpft wird
  METHOD on_my_event.
    WRITE: / '2. lcl_eventhandler=>on_my_event:'.
    WRITE: / '   Name:', sender->get_name( ).
    WRITE: / '    txt:', txt.
    WRITE: / '    val:', val.
  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
* Objekt erzeugen
  DATA(o_evt) = NEW lcl_demo( 'Aufrufer-Objekt' ).

* Handler registrieren: Zuordnung von Eventhandler "on_my_event" zu Objekt der Demo-Klasse mit Eventtrigger für my_event
  SET HANDLER lcl_eventhandler=>on_my_event FOR o_evt.

* Funktionsaufruf, welcher den Event triggert
  o_evt->write( ).

Weiterführende Infos: Link und Link

[ABAP] Beispiel für Implementation einer lokalen Klasse

CLASS cl_one DEFINITION.
* Public-Deklarationen, global inner- und außerhalb des Objektes sichtbar
  PUBLIC SECTION.
    DATA: pu_val3 TYPE i.        " dyn. Variable, nur zur Obj-Laufzeit verfügbar

    CLASS-DATA: txt TYPE string. " statische Public-Variable
    CLASS-DATA: int TYPE i.      " statische Public-Variable

* statische Methode, hat keinen Zugriff auf pu_val3
    CLASS-METHODS: function_one
      IMPORTING
                i_txt          TYPE string
      RETURNING VALUE(ret_val) TYPE string. " wenn RETURNING VALUE, dann kein EXPORTING oder CHANGING möglich

* statische Methode, hat keinen Zugriff auf pu_val3
    CLASS-METHODS: function_two
      IMPORTING
                i_txt          TYPE string
                i_val          TYPE i
      RETURNING VALUE(ret_val) TYPE string. " wenn RETURNING VALUE, dann kein EXPORTING oder CHANGING möglich

* dynamische Methode, hat Zugriff auf pu_val3
    METHODS: function_three
      IMPORTING
                i_val1         TYPE i DEFAULT 10 " Default-Wert, falls Parameter nicht gesetzt
                i_val2         TYPE i DEFAULT 20 " Default-Wert, falls Parameter nicht gesetzt
      RETURNING VALUE(ret_val) TYPE i.           " wenn RETURNING VALUE, dann kein EXPORTING oder CHANGING möglich

* dynamische Methode, einfaches Exceptionhandling
    METHODS: function_four
      IMPORTING
                i_val1         TYPE i
      RETURNING VALUE(ret_val) TYPE i
      RAISING   cx_sy_arithmetic_error.

    METHODS: constructor.
* Private-Deklarationen, nur innerhalb der Klasse sichtbar
  PRIVATE SECTION.
    DATA: pr_val3 TYPE i.
ENDCLASS.

CLASS cl_one IMPLEMENTATION.
* Constructor der Klasse
  METHOD constructor.
    me->pr_val3 = 100.
  ENDMETHOD.
* Funktion mit einem Übergabeparameter
  method function_one.
    DATA: s TYPE string VALUE 'Return: '.
    ret_val = |{ s } { i_txt }|.
  ENDMETHOD.

* Funktion mit zwei Übergabeparametern
  METHOD function_two.
    ret_val = |{ i_txt } { i_val }|.
  ENDMETHOD.

* Funktion mit zwei Übergabeparametern und DEFAULT-Werten
* Verwendung des me-> Operators für den Zugriff auf Attribute der Klasse
  METHOD function_three.
    ret_val = ( me->pu_val3 + me->pr_val3 ) * ( i_val1 + i_val2 ).
  ENDMETHOD.

* Funktion mit einem Übergabeparameter
* löst bei DIV0 -> cx_sy_arithmetic_error aus
  METHOD function_four.
    ret_val = 100 / i_val1.
  ENDMETHOD.
ENDCLASS.

INITIALIZATION.
  cl_one=>int = 1.
  cl_one=>txt = |Test.|.

START-OF-SELECTION.
* statische Objektaufrufe
  WRITE: / cl_one=>int.
  WRITE: / cl_one=>txt.

  WRITE: / cl_one=>function_one( |Input.| ).

  WRITE: / cl_one=>function_two( i_txt = |Input2:|
                                 i_val = 1 ).

* dynamische Objektaufrufe
  DATA(o_cl_one) = NEW cl_one( ).
  o_cl_one->pu_val3 = 10.
  WRITE: / o_cl_one->function_three( ).
  WRITE: / o_cl_one->function_three( i_val1 = 1
                                     i_val2 = 2 ).

* Exception abfangen
  TRY.
      WRITE: / o_cl_one->function_four( 0 ). " Division durch 0 auslösen
    CATCH cx_root INTO DATA(e_text).
      WRITE: / e_text->get_text( ).
  ENDTRY.