[JavaScript] Prototyping

function Person(name) {
  this.Vorname = name;
}

// p1 -> Attribut "Nachname" für nur dieses Objekt
let p1 = new Person("Ede");
p1.Alter = 60;
console.log(p1.Vorname + " " + p1.Alter);

// p2 -> hat keinen Attribut "Alter"
let p2 = new Person("Horst");
console.log(p2.Vorname + " " + p2.Alter);

// neue Eigenschaft im Prototyp ("Basisklasse") für alle Personen hinzufügen
Person.prototype.Alter = 70;

// p2 hat nun auch ein Attribut "Alter"
console.log(p2.Vorname + " " + p2.Alter);

[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));

[JavaScript] Klassendeklaration über „function“

Variante 1 (public)

// https://www.phpied.com/3-ways-to-define-a-javascript-class/
// https://developer.mozilla.org/de/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript

// Klasse Person über "function" abbilden
function Person(vorname, nachname, alter) {
  this.Vorname = vorname;
  this.Nachname = nachname;
  this.Alter = alter;
  this.getText = function(type){
    var text = "";
     
    switch (type) {
      case "1":
        text = this.Vorname;
        break;
      case "2":
        text = this.Nachname;
        break;
      case "3":
        text = this.Alter;
        break;
      default:
        text = "-";
        break;
    }
     
    return text;
  };
}

var p = new Person("Udo", "Mustermann", 30);

// Datenausgabe
console.log(p.getText("1"));

Variante 2 (private und public)

function User() {

  // private
  a = 1;
  
  function private() {
    return a;
  }

  // public
  this.b = 2;

  this.public = function() {
    return this.b;
  };
}

let u = new User();
// error
//u.private();
// undefined
console.log(u.a);
// 2
console.log(u.b);
// 2
console.log(u.public());

[JavaScript] Einfache Objektdefinition

einfache Objektdefinition mit Literalen

// https://www.w3schools.com/js/js_objects.asp
// https://www.phpied.com/3-ways-to-define-a-javascript-class/

let person = {
  Vorname: "Horst",
  Nachname: "Mustermann",
  Alter: 65,
  getText: function(type){
    let text = "";
     
    switch (type) {
      case "1":
        text = this.Vorname;
        break;
      case "2":
        text = this.Nachname;
        break;
      case "3":
        text = this.Alter;
        break;
      default:
        text = "-";
        break;
    }
     
    return text;
  }
};

// Horst -> Klaus
person["Vorname"] = "Klaus";

// Datenausgabe
console.log(person.Vorname);
console.log(person["Vorname"]);
console.log(person.getText("1"));
console.log(person.getText("2"));
console.log(person.getText("3"));

einfache Objektdefinition mit new Object

let person = new Object();

person.Vorname = "Horst";
person.Nachname = "Mustermann";
person.Alter = 65;
person.getText = function(type){
  let text = "";
   
  switch (type) {
    case "1":
      text = this.Vorname;
      break;
    case "2":
      text = this.Nachname;
      break;
    case "3":
      text = this.Alter;
      break;
    default:
      text = "-";
      break;
  }
   
  return text;
};
 
// Datenausgabe
console.log(person.Vorname);
console.log(person["Vorname"]);
console.log(person.getText("1"));
console.log(person.getText("2"));
console.log(person.getText("3"));

alternative Objektdefinition mit new Object + Literalen

let person = new Object({
  Vorname : "Horst",
  Nachname : "Mustermann",
  Alter : 65,
  getText : function(type){
      let text = "";
       
      switch (type) {
        case "1":
          text = this.Vorname;
          break;
        case "2":
          text = this.Nachname;
          break;
        case "3":
          text = this.Alter;
          break;
        default:
          text = "-";
          break;
      }
       
      return text;
  }
});

// Datenausgabe
console.log(person.Vorname);
console.log(person["Vorname"]);
console.log(person.getText("1"));
console.log(person.getText("2"));
console.log(person.getText("3"));

[ABAP] Datenausgabe mit cl_demo_output

Demoprogramme

* DEMO_USAGE_OUTPUT_GET
* DEMO_USAGE_OUTPUT_STATIC
* DEMO_USAGE_OUTPUT_INSTANCE
* DEMO_USAGE_OUTPUT_STREAM

Text mit Abschnitten

* Abschnitt 1
cl_demo_output=>begin_section( '1. Überschrift' ).
cl_demo_output=>begin_section( '1.1 Überschrift' ).
* Text
cl_demo_output=>write_text( 'Text 1.1' ).
cl_demo_output=>write( 'Text 1.1 non proportional' ).
cl_demo_output=>end_section( ).
cl_demo_output=>end_section( ).
* Abschnitt 2
cl_demo_output=>begin_section( '2. Überschrift' ).
cl_demo_output=>begin_section( '2.1 Überschrift' ).
* Text
cl_demo_output=>write_text( 'Text 2.1' ).
cl_demo_output=>write( 'Text 2.1 non proportional' ).
cl_demo_output=>end_section( ).
cl_demo_output=>end_section( ).
* alles anzeigen
cl_demo_output=>display( ).

Variablen, Strukturen, Tabellen

TYPES: BEGIN OF ty_struct,
         f1 TYPE string,
         f2 TYPE i,
       END OF ty_struct.

TYPES: ty_it_tab TYPE STANDARD TABLE OF ty_struct WITH DEFAULT KEY.

DATA(lv_struct) = VALUE ty_struct( f1 = 'Field1' f2 = 1 ).
DATA(it_tab) = VALUE ty_it_tab( ( f1 = 'T1' f2 = 1 )
                                ( f1 = 'T2' f2 = 2 )
                                ( f1 = 'T3' f2 = 3 ) ).

cl_demo_output=>write_data( value = -100         name = 'Zahl' ).
cl_demo_output=>write_data( value = 'ein String' name = 'Text' ).
cl_demo_output=>write_data( value = lv_struct    name = 'Struct' ).
cl_demo_output=>write_data( value = it_tab       name = 'Tab' ).
* alles anzeigen
cl_demo_output=>display( ).

Trennlinie

cl_demo_output=>write_text( 'Oben' ).
cl_demo_output=>line( ).
cl_demo_output=>write_text( 'Unten' ).
* alles anzeigen
cl_demo_output=>display( ).

HTML

* HTML hinzufügen
cl_demo_output=>write_html( '<b>Text bold</b>' ).
* HTML anzeigen
cl_demo_output=>display_html( '<i>Text italic</i>' ).

XML

DATA: lv_xml TYPE string.
...
cl_demo_output=>display_xml( lv_xml ).

JSON

DATA: lv_json TYPE xstring.
...
cl_demo_output=>display_json( lv_json ).

Plaintext ausgeben

SELECT * FROM tnapr INTO TABLE @DATA(it_tnapr).
cl_demo_output=>new( 'TEXT' )->display( it_tnapr ).

HTML-Code generieren lassen

SELECT * FROM mara INTO TABLE @DATA(it_mara).
IF sy-subrc = 0.
  cl_demo_output=>write_data( it_mara ).
* HTML-Code vom Demo-Output holen
  DATA(lv_html) = cl_demo_output=>get( ).
* Daten im Inline-Browser im SAP-Fenster anzeigen
  cl_abap_browser=>show_html( EXPORTING
                                title        = 'Daten aus der Tabelle MARA'
                                html_string  = lv_html
                                container    = cl_gui_container=>default_screen ).

* cl_gui_container=>default_screen erzwingen
  WRITE: space.
ENDIF.

Links

[ABAP] OO: Variablen, Strukturen, interne Tabellen, Objektreferenzen anlegen

Variable anlegen

* int
DATA(lv_int) = 1.
DATA(lv_int_empty) = VALUE i( ).
 
* float
DATA(lv_float_empty) = VALUE f( ).
DATA(lv_float) = CONV f( '0.1' ).
 
* char
DATA(lv_char) = 'ABCD'.
 
* string
DATA(lv_empty_string) = ||.
DATA(lv_string) = |Text|.
 
* bool
DATA(lv_bool) = abap_true.
 
* DDIC-Typ (z.B. MATNR)
DATA(lv_matnr) = CONV matnr( '1234567890' ).
DATA(lv_matnr_empty) = VALUE matnr( ).

Struktur anlegen

* definiert vom Anwender
TYPES: BEGIN OF ty_sflight,
         carrid TYPE sflight-carrid,
         connid TYPE sflight-connid,
       END OF ty_sflight.

DATA(lv_struct) = VALUE ty_sflight( carrid = 'LH'
                                    connid = '0123' ).

* Strukturtyp aus DDIC (leer)
DATA(lv_headdata_empty) = VALUE bapimathead( ).

* Strukturtyp aus DDIC (gefüllt)
DATA(lv_headdata) = VALUE bapimathead( material      = '1234567890'
                                       basic_view    = abap_true
                                       purchase_view = abap_true
                                       account_view  = abap_true ).

interne Tabelle anlegen

* definiert vom Anwender
TYPES: BEGIN OF ty_sflight,
         carrid TYPE sflight-carrid,
         connid TYPE sflight-connid,
       END OF ty_sflight.

TYPES: ty_it_sflight TYPE STANDARD TABLE OF ty_sflight WITH DEFAULT KEY.

DATA(it_tab) = VALUE ty_it_sflight( ( carrid = 'LH' connid = '0123')
                                    ( carrid = 'AA' connid = '3210') ).

* Stringtable aus DDIC (leer)
DATA(it_stringtab_empty) = VALUE stringtab( ).

* Stringtable aus DDIC (gefüllt)
DATA(it_stringtab) = VALUE stringtab( ( |Udo| )
                                      ( |Heinz| )
                                      ( |Klaus| ) ).

Objektreferenz anlegen

* Objektreferenz auf Klasse ALV-Grid
DATA(o_alv) = NEW cl_gui_alv_grid( i_parent      = cl_gui_container=>default_screen
                                   i_appl_events = abap_true ).

* Referenz auf int
DATA(lv_int) = 1.
DATA(o_int) = REF #( lv_int ).

* Referenz auf stringtab
DATA(it_stringtab) = VALUE stringtab( ).
DATA(o_tab) = REF #( it_stringtab ).

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