[JavaScript] Klassenbasierte Vererbung

// https://javascript.info/class-inheritance
// https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Klassen

// ab ES6
class Car {
  constructor(name) {
    this.name = name;
  }

  drive() {
    console.log("Driving: " + this.name);
  }
}

class Audi extends Car {
  quadro() {
    console.log("Quadro: " + this.name);
  }
}

let a = new Audi("A4");
a.drive();
a.quadro();

[JavaScript] Eine Klasse definieren

Klassendefinition ab ES6

// https://javascript.info/class
// https://javascript.info/property-accessors
class Rechteck
{
  // Konstruktor
  constructor(h, b) {
    this.h = h;
    this.b = b;
  }
   
  // public Properties
  get flaeche() {
    return this.Flaeche();
  }
 
  set hoehe(value) {
    this.h = value;
  }
  
  set breite(value) {
    this.b = value;
  }
  
  // public Methoden
  Flaeche() {
    return this.h * this.b;
  }
  
  // statische Methoden
  static Calc(h, b) {
    return h * b;
  }
}
 
const q = new Rechteck(10, 10);
 
console.log(q.flaeche);
q.hoehe = 5;
console.log(q.Flaeche());
console.log(Rechteck.Calc(2, 3));
console.log(Object.getOwnPropertyNames(Rechteck.prototype));

herkömmlich über „function“

function Rechteck(h, b)
{ 
    this.h = h;
    this.b = b;
   
    Rechteck.prototype.Flaeche = function() {
      return this.h * this.b;
    }
}
 
let q = new Rechteck(10, 10);
 
console.log(q.Flaeche());
console.log(Object.getOwnPropertyNames(Rechteck.prototype));

[JavaScript] Fortgeschrittene Objektdefinition: Revealing Module Pattern (Kapselung plus öffentliche Schnittstelle)

// https://wiki.selfhtml.org/wiki/JavaScript/Module_und_Kapselung

// Klasse / Modul definieren
// Grundmodul
let oModule = (function() {
  // private
  let priv1 = 100;
  let priv2 = 200;
   
  function priv_func1(var1, var2) {
    return var1 + var2 + priv1;
  }
 
  function priv_func2(var1, var2) {
    return var1 + var2 + priv2;
  }
   
  // public 
  return {
    public_func1: function(var1, var2) {
      return priv_func1(var1, var2) + priv_func2(var1, var2);
    }
  };
 
})();

// Erweiterung des Grundmoduls um public und private Methoden
(function (module) {
  // private
  let priv3 = 200;
  
  function priv_func3(var1, var2) {
    return var1 + var2 + priv3;
  }
  
  // public
  module.public_func2 = function(var1, var2) {
    return priv_func3(var1, var2);
  };
})(oModule);

// ok -> 306
console.log(oModule.public_func1(1, 2));
// ok -> 203
console.log(oModule.public_func2(1, 2));
// undefined
console.log(oModule.priv1);
// undefined
console.log(oModule.priv3);
// "error"
console.log(oModule.priv_func1(1, 2));
// "error"
console.log(oModule.priv_func3(1, 2));

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