ABAP Objects

Objektorientiertes ABAP für moderne Clean Core SAP Systeme

Interfaces

ABAP Interface

Definition Wikipedia

Eine Schnittstelle oder ein Interface (englisch interface oder protocol) definiert in der objektorientierten Programmierung, welche Methoden in den unterschiedlichen Klassen u. Ä. vorhanden sind oder vorhanden sein müssen. Sie legt die Namen und die Signatur der Methoden, also die Parametertypen und den Rückgabetyp, fest.

Interfaces in ABAP Objects

  • Ein ABAP Interface ist eigenes Entwicklungsobjekt im ABAP (analog zur ABAP Klasse)
  • In Eclipse anlegen über New -> ABAP Interface
  • Im Interface werden vor allem die Methoden und deren Parameter definiert
  • Interfaces enthalten keine Implementierungen, können aber Konstanten, Typen u.a. enthalten
  • Klassen binden Interfaces durch INTERFACES <interface>. in der PUBLIC SECTION ein
  • Das Anlegen von Methoden des Interface wird durch Eclipse Quick-Fix unterstützt

Interface Beispiel

Interface

INTERFACE zif_bc_aoo_simple_die
  PUBLIC .
    METHODS get_description 
        RETURNING VALUE(rv_description) TYPE string.
    METHODS roll 
        RETURNING VALUE(rv_number) TYPE i.
ENDINTERFACE.

  • Interfaces sind PUBLIC
  • Einbinden in Klassen durch INTERFACES <interface>. in der PUBLIC SECTION
  • Methodennamen von Interface-Methoden verwenden ~ als Trennzeichen
  • Interface-Methoden lösen damit keine Namenskonflikte mit gleichnamigen Methoden aus
  • Interfaces sind wichtig für das API Design und zur Abbildung der objektorientierten Polymorphie

Klasse

CLASS zcl_bc_aoo_##_die_har DEFINITION
  PUBLIC
  CREATE PUBLIC
  INHERITING FROM ZCL_BC_AOO_##_DIE_ENC.

  PUBLIC SECTION.
    INTERFACES zif_bc_aoo_simple_die.
  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.


CLASS zcl_bc_aoo_##_die_har IMPLEMENTATION.
  METHOD zif_bc_aoo_simple_die~roll.
    return roll(  ).
  ENDMETHOD.

  METHOD zif_bc_aoo_simple_die~get_description.
    return get_description(  ).
  ENDMETHOD.
ENDCLASS.

Übung: "Harmonisiert"

Überblick

Wir lassen die Würfel der Teilnehmer gegeneinander antreten. Dazu müssen wir sie "unter einen Hut" bringen. Wir nutzen dafür die Vererbungshierarchie und Interfaces. Am Ende spielen die Würfel der Teilnehmer gegeneinander.

Lernziele

  • ABAP Klasse mit Interfaces implementieren
  • Vererbungshierarchie verstehen
  • Casting verstehen
  • Einblick in die dynamische Programmierung
  • Einblick in API Design Vorgehensweisen

Harmonisiert

Beispiele aus der Übung

Dynamische Erstellung der Instanzen

METHODS create_instance
    IMPORTING
            iv_class           TYPE string
            iv_id              TYPE string OPTIONAL
    RETURNING VALUE(ro_instance) TYPE REF TO object.
METHOD create_instance.
    TRY.
        IF iv_id IS INITIAL.
            CREATE OBJECT ro_instance TYPE (iv_class).
        ELSE.
            CREATE OBJECT ro_instance TYPE (iv_class)
                EXPORTING
                    iv_id = iv_id.
        ENDIF.
    CATCH cx_root INTO DATA(lx_exc).
        DATA(lv_error) = lx_exc->get_text(  ).
    ENDTRY.
ENDMETHOD.

CAST über Klassenhierarchie

DATA(lo_instance) = create_instance(
          iv_class = |ZCL_BC_AOO_##_DIE_INH|
          iv_id    = |DEMO-VERERBUNG|
      ).
IF lo_instance IS BOUND.
    DATA(lo_die) = CAST zcl_bc_aoo_number_die( lo_instance ).
    lo_die->roll( ).
ENDIF.

CAST über Interface

DATA(lo_instance) = create_instance( |ZCL_BC_AOO_##_DIE_ENC| ).
IF lo_instance IS BOUND.
    DATA(lo_die) = CAST zif_bc_aoo_simple_die( lo_instance ).
    lo_die->roll( ).
ENDIF.

CAST Beispiele mit Interface-Nutzung

Aufruf

DATA(my_class) = NEW ZCL_MY_CLASS( ).
out->write( |A1: { my_class->get_description( ) }| ).
out->write( |A2: { my_class->zif_my_interface_1~get_description( ) }| ).
out->write( |A3: { my_class->zif_my_interface_2~get_description( ) }| ).

DATA(my_intf_1) = CAST ZIF_MY_INTERFACE_1( my_class ).
out->write( |B1: { my_intf_1->get_description( ) }| ).

DATA(my_intf_2) = CAST ZIF_MY_INTERFACE_1( my_class ).
out->write( |B2: { my_intf_2->get_description( ) }| ).

DATA(my_class_2) = CAST ZCL_MY_CLASS( my_intf_1 ).
out->write( |C1: { my_class_2->get_description( ) }| ).

Ausgabe

A1: Description aus ZCL_MY_CLASS
A2: Description aus ZIF_MY_INTERFACE_1
A3: Description aus ZIF_MY_INTERFACE_2
B1: Description aus ZIF_MY_INTERFACE_1
B2: Description aus ZIF_MY_INTERFACE_2
C1: Description aus ZCL_MY_CLASS

Klasse Definition

CLASS zcl_my_class DEFINITION PUBLIC CREATE PUBLIC.
  PUBLIC SECTION.
    INTERFACES zif_my_interface_1.
    INTERFACES zif_my_interface_2.
    METHODS get_description RETURNING VALUE(rv_text).
ENDCLASS.

Interface 1 Definition

INTERFACE zif_my_interface_1 PUBLIC.
    METHODS get_description RETURNING VALUE(rv_text).
ENDINTERFACE.

Interface 2 Definition

INTERFACE zif_my_interface_2 PUBLIC.
    METHODS get_description RETURNING VALUE(rv_text).
ENDINTERFACE.

Hinweis: <target> ?= <source> für CAST möglich

Ausblick: API Design mit Factory-Klassen und Interfaces (Kopiervorlage)

Aufruf

DATA(lo_api) = zcl_my_factory=>create_my_api(  ).
out->write( lo_api->execute( |Demo Kontext| ) ).

API Interface

INTERFACE zif_my_api PUBLIC.
  METHODS execute IMPORTING iv_input TYPE string
                  RETURNING VALUE(rv_result) TYPE string.
ENDINTERFACE.

API Default Implementierung

CLASS zcl_my_api DEFINITION PUBLIC CREATE PUBLIC .
  PUBLIC SECTION.
    interfaces zif_my_api.
ENDCLASS.
CLASS zcl_my_api IMPLEMENTATION.
  METHOD zif_my_api~execute.
    return |API executd: { iv_input }|.
  ENDMETHOD.
ENDCLASS.

API Factory Klasse

CLASS zcl_my_factory DEFINITION PUBLIC CREATE PUBLIC.
  PUBLIC SECTION.
    CLASS-METHODS: create_instance
        IMPORTING iv_interface type string
        RETURNING VALUE(ro_instance) type ref to object.
    CLASS-METHODS: create_my_api
        RETURNING VALUE(ro_instance) type ref to zif_my_api.
ENDCLASS.
CLASS zcl_my_factory IMPLEMENTATION.
  METHOD create_instance.
    data(lv_class) = iv_interface.
    "TODO: select from customized table
    replace 'ZIF_' in lv_class with 'ZCL_'.
    try.
        create object ro_instance type (lv_class).
    catch cx_root into data(lx_exc).
    ENDTRY.
  ENDMETHOD.

  METHOD create_my_api.
    return cast zif_my_api( create_instance( |ZIF_MY_API| ) ).
  ENDMETHOD.
ENDCLASS.