Skip to content

13. Die Klassen

Image

Hier stellen wir die Klassen von ECMAScript 6 vor. Zunächst zeigen wir, dass die Funktionen bereits als Klassen verwendet werden können.

13.1. Skript [class-00]

Das folgende Skript zeigt eine ungewöhnliche Verwendung von Funktionen. Sie werden hier als Objekte verwendet.


'use strict';
// Eine Funktion kann als Objekt verwendet werden

// eine leere Hülle
function f() {

}
//, der von außen Eigenschaften zugewiesen werden
f.prop1 = "val1";
f.show = function () {
  console.log(this.prop1);
}
// Verwendung von f
f.show();

// eine Funktion g, die wie eine Klasse funktioniert
function g() {
  this.prop2 = "val2";
  this.show = function () {
    console.log(this.prop2);
  }
}
// Instanziierung der Funktion mit [new]
new g().show();

Kommentare

  • Zeilen 5–7: Der Funktionskörper von f definiert keine Eigenschaften;
  • Zeilen 9–12: Der Funktion f werden von außen Eigenschaften zugewiesen;
  • Zeile 14: Verwendung der Funktion (des Objekts) f. Beachten Sie, dass man nicht [f()] schreibt, sondern einfach [f]. Dies ist die Notation für ein Objekt;
  • Zeilen 17–22: Es wird eine Funktion [g] definiert, als wäre sie eine Klasse mit Eigenschaften und Methoden;
  • Zeile 24: Die Funktion [g] wird von [new g()] instanziiert;

Ausführungsergebnisse


[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\classes\class-00.js"
val1
val2

ES6 hat das Konzept der Klasse eingeführt, wodurch wir nun vermeiden können, über Funktionen zu gehen, um Klassen zu erhalten.

13.2. Skript [class-01]

Das Skript [class-01] stellt eine Klasse [Personne] vor:


// Klasse
class Personne {

  // Konstruktor
  constructor(nom, prénom, âge) {
    this.nom = nom;
    this.prénom = prénom;
    this.âge = âge;
  }

  // Getter und Setter
  get nom() {
    return this._nom;
  }
  set nom(value) {
    this._nom = value;
  }

  get prénom() {
    return this._prénom;
  }
  set prénom(value) {
    this._prénom = value;
  }

  get âge() {
    return this._âge;
  }
  set âge(value) {
    this._âge = value;
  }

  // toString in JSON
  toString() {
    return JSON.stringify(this);
  }
}

// Aufruf der Klasse
function main() {
  const personne = new Personne("Poirot", "Hercule", 66);
  console.log("personne=", personne.toString(), typeof (personne), personne instanceof (Personne));
}

// Aufruf von „main“
main();

Kommentare

  • Zeile 2: Das Schlüsselwort [class] bezeichnet eine Klasse;
  • Zeilen 5–9: Das Schlüsselwort [constructor] bezeichnet den Konstruktor der Klasse. Es darf höchstens einen geben. Er dient dazu, eine Instanz der Klasse zu erstellen und zu initialisieren. Beachten Sie, dass es keine Deklaration der Eigenschaften [nom, prénom, âge] gibt;
  • Zeilen 11–36: Eigenschaften der Klasse. Hier finden sich Elemente wieder, die bereits im Abschnitt über Objekte 4 auf Seite 44 behandelt wurden. Lediglich die Syntax unterscheidet sich;
  • Zeile 41: Erstellung eines Objekts vom Typ [Personne]. Von nun an wird das Objekt [personne] wie ein Literalobjekt verwendet. [typeof (personne)] ist gleich „object“ und der Ausdruck [personne instanceof (Personne)] ist wahr. Es ist also möglich, den genauen Typ einer Klasseninstanz zu ermitteln;

Ausführungsergebnisse


[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\classes\class-01.js"
personne= {"_nom":"Poirot","_prénom":"Hercule","_âge":66} object true

13.3. Skript [class-02]

Dieses Skript veranschaulicht die Möglichkeit, eine Klasse mit dem Schlüsselwort [extends] zu erben.

Zunächst isolieren wir die Klasse [Personne] in einem Modul [Personne.js]:


// Klasse
class Personne {

  // Konstruktor
  constructor(nom, prénom, âge) {
    this.nom = nom;
    this.prénom = prénom;
    this.âge = âge;
  }

  // Getter und Setter
  get nom() {
    return this._nom;
  }
  set nom(value) {
    this._nom = value;
  }

  get prénom() {
    return this._prénom;
  }
  set prénom(value) {
    this._prénom = value;
  }

  get âge() {
    return this._âge;
  }
  set âge(value) {
    this._âge = value;
  }

  // toString in JSON
  toString() {
    return JSON.stringify(this);
  }
}
// Klasse exportieren
export default Personne;
  • Zeile 39: Wir exportieren die Klasse [Personne], damit Skripte sie importieren können;

Das Skript [class-02] legt eine Klasse [Enseignant] an, die von der Klasse [Personne] abgeleitet ist:


// Importe
import Personne from './Personne';

// Klasse
class Enseignant extends Personne {

  // Konstruktor
  constructor(nom, prénom, âge, discipline) {
    super(nom, prénom, âge);
    this.discipline = discipline;
  }

  // Getter und Setter
  get discipline() {
    return this._discipline;
  }
  set discipline(value) {
    this._discipline = value;
  }

}

// Aufruf der Klasse
function main() {
  const enseignant = new Enseignant("Poirot", "Hercule", 66, "détective");
  console.log("enseignant=", enseignant.toString(), typeof (enseignant), enseignant instanceof Enseignant);
}

// Aufruf von „main“
main();

Kommentare

  • Zeile 2: Die Klasse [Personne] wird aus dem Modul [Personne.js] importiert, das sich im selben Ordner wie [class-02] befindet;
  • Zeile 5: Die Klasse [Enseignant] erweitert (erbt von) die Klasse [Personne] mit dem Schlüsselwort [extends]: sie fügt ihr eine Eigenschaft [_discipline] mit den dazugehörigen Getter- und Setter-Methoden hinzu;
  • Zeilen 8–11: Der Konstruktor der Klasse [Enseignant] erhält vier Werte zur Initialisierung der vier Eigenschaften der Klasse;
  • Zeile 9: Das Schlüsselwort [super] ruft den Konstruktor der übergeordneten Klasse [Personne] auf, der somit die Eigenschaften [_nom, _prénom, _âge] initialisiert;
  • Zeile 10: Die Eigenschaft [_discipline], die zur Klasse [Enseignant] gehört, wird initialisiert;
  • Zeilen 14–19: Der Getter und der Setter der Eigenschaft [_discipline];
  • Zeile 25: Es wird ein Objekt vom Typ [Enseignant] erstellt;
  • Zeile 26: Die Methode [enseignant.toString()] wird verwendet. Die Klasse [Enseignant] verfügt nicht über diese Methode. In diesem Fall wird automatisch die Methode der übergeordneten Klasse verwendet. Diese Methode bewirkt, dass der Ausdruck [JSON.stringify(this)] – wobei [this] hier ein Objekt vom Typ [Enseignant] und kein Objekt vom Typ [Personne] ist – ausgewertet wird. Dies wird in der objektorientierten Programmierung als Polymorphismus von Klassen bezeichnet. Ein großes Wort für JavaScript, das keine objektorientierte Sprache ist. Dennoch tut JavaScript hier genau das, was man von ihm erwartet: Es zeigt tatsächlich einen Lehrer an;

Die Ergebnisse der Ausführung lauten wie folgt:


[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\classes\class-02.js"
enseignant= {"_nom":"Poirot","_prénom":"Hercule","_âge":66,"_discipline":"détective"} object true
  • Zeile 2: JavaScript erkennt korrekt, dass die Variable [enseignant] vom Typ [Enseignant] ist;

13.4. Skript [class-03]

Das Skript [class-03] zeigt, dass eine untergeordnete Klasse Eigenschaften und Methoden ihrer übergeordneten Klasse neu definieren kann. Hier definieren wir die Methode [toString] der übergeordneten Klasse neu:


// Importe
import Personne from './Personne';

// Klasse
class Enseignant extends Personne {

  // Konstruktor
  constructor(nom, prénom, âge, discipline) {
    super(nom, prénom, âge);
    this.discipline = discipline;
  }

  // Getter und Setter
  get discipline() {
    return this._discipline;
  }
  set discipline(value) {
    this._discipline = value;
  }

  // Neudefinition von toString
  toString() {
    return "[Enseignant]" + JSON.stringify(this);
  }
}

// Aufruf der Klasse
function main() {
  const enseignant = new Enseignant("Poirot", "Hercule", 66, "détective");
  console.log("enseignant=", enseignant.toString(), typeof (enseignant), enseignant instanceof Enseignant);
}

// Aufruf von „main“
main();

Die Ergebnisse der Ausführung lauten wie folgt:


[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\classes\class-03.js"
enseignant= [Enseignant]{"_nom":"Poirot","_prénom":"Hercule","_âge":66,"_discipline":"détective"} object true

13.5. Skript [class-04]

Das Skript [class-04] veranschaulicht erneut den Polymorphismus in der Praxis: Wo eine Funktion einen formalen Parameter vom Typ [Personne] erwartet, kann ein abgeleiteter Typ wie [Enseignant] übergeben werden. Tatsächlich verfügt der Typ [Enseignant] aufgrund der Ableitung über alle Attribute des Typs [Personne].

Zunächst isolieren wir den Typ [Enseignant] in einem Modul [Enseignant.js]:


// Importe
import Personne from './Personne';

// Klasse
class Enseignant extends Personne {

  // Konstruktor
  constructor(nom, prénom, âge, discipline) {
    super(nom, prénom, âge);
    this.discipline = discipline;
  }

  // Getter und Setter
  get discipline() {
    return this._discipline;
  }
  set discipline(value) {
    this._discipline = value;
  }

}

// Klasse exportieren
export default Enseignant;
  • Zeile 24: Die Klasse [Enseignant] wird exportiert, damit andere Skripte sie importieren können;

Das Skript [class-04] lautet wie folgt:


// Importe
import Enseignant from './Enseignant';
import Personne from './Personne';

// Funktion, die eine Person als Parameter akzeptiert
function show(personne) {
  // in jedem Fall
  console.log("paramètre=", personne.toString(), typeof (personne));
  // Instanz von „Person“
  if (personne instanceof Personne) {
    console.log("personne=", personne.toString());
  }
  // Instanz von „Lehrer“
  if (personne instanceof Enseignant) {
    console.log("enseignant=", personne.toString());
  }
}

// Aufruf von „show“ mit einem Lehrer
show(new Enseignant("Poirot", "Hercule", 66, "détective"));
show(new Personne("Marple", "Miss", 70));
  • Zeile 6: Die Funktion [show] erwartet einen Typ [Personne] oder einen davon abgeleiteten Typ;
  • Zeile 8: Die Zeichenkette des Parameters und dessen Typ werden angezeigt. Dort findet man [object];
  • Zeilen 10–16: Man kann feststellen, ob es sich um den Typ [Personne] oder den Typ [Enseignant] handelt. Der Code kann somit an den tatsächlichen Typ des Parameters angepasst werden;

Die Ergebnisse der Ausführung lauten wie folgt:


[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\classes\class-04.js"
paramètre= {"_nom":"Poirot","_prénom":"Hercule","_âge":66,"_discipline":"détective"} object
personne= {"_nom":"Poirot","_prénom":"Hercule","_âge":66,"_discipline":"détective"}
enseignant= {"_nom":"Poirot","_prénom":"Hercule","_âge":66,"_discipline":"détective"}
paramètre= {"_nom":"Marple","_prénom":"Miss","_âge":70} object
personne= {"_nom":"Marple","_prénom":"Miss","_âge":70}
  • Zeilen 4 und 6: JavaScript erkennt den Typ der Klasseninstanzen korrekt;