13. Klassen

Hier stellen wir ECMAScript 6-Klassen vor. Zunächst zeigen wir, dass Funktionen bereits als Klassen verwendet werden können.
13.1. Skript [class-00]
Das folgende Skript veranschaulicht eine ungewöhnliche Verwendung von Funktionen. Hier werden sie als Objekte verwendet.
'use strict';
// a function can be used as an object
// an empty shell
function f() {
}
// to which external properties are attributed
f.prop1 = "val1";
f.show = function () {
console.log(this.prop1);
}
// use of f
f.show();
// a function g operating as a class
function g() {
this.prop2 = "val2";
this.show = function () {
console.log(this.prop2);
}
}
// instantiate the function with [new]
new g().show();
Kommentare
- Zeilen 5–7: Der Körper der Funktion 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 wir nicht [f()] schreiben, sondern einfach [f]. Dies ist die Notation für ein Objekt;
- Zeilen 17–22: Wir definieren eine Funktion [g], als wäre sie eine Klasse mit Eigenschaften und Methoden;
- Zeile 24: Die Funktion [g] wird durch [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
Mit ES6 wurde das Konzept der Klassen eingeführt, wodurch wir nun vermeiden können, Funktionen zum Erstellen von Klassen zu verwenden.
13.2. Skript [class-01]
Das Skript [class-01] stellt eine Klasse [Person] vor:
// class
class Personne {
// manufacturer
constructor(nom, prénom, âge) {
this.nom = nom;
this.prénom = prénom;
this.âge = âge;
}
// getters and setters
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 to JSON
toString() {
return JSON.stringify(this);
}
}
// class call
function main() {
const personne = new Personne("Poirot", "Hercule", 66);
console.log("personne=", personne.toString(), typeof (personne), personne instanceof (Personne));
}
// hand call
main();
Kommentare
- Zeile 2: Das Schlüsselwort [class] bezeichnet eine Klasse;
- Zeilen 5–9: Das Schlüsselwort [constructor] bezeichnet den Klassenkonstruktor. Es kann höchstens einen geben. Er dient dazu, eine Instanz der Klasse zu erstellen und zu initialisieren. Beachten Sie, dass es keine Deklaration der Eigenschaften [last_name, first_name, age] gibt;
- Zeilen 11–36: Klassen-Eigenschaften. Hier sehen wir Elemente, die bereits im Abschnitt über Objekte 4 auf Seite 44 behandelt wurden. Nur die Syntax unterscheidet sich;
- Zeile 41: Erstellung eines Objekts vom Typ [Person]. Von nun an wird das Objekt [person] als Literalobjekt verwendet. [typeof (person)] ergibt „object“ und der Ausdruck [person instanceof (Person)] ist wahr. Es ist daher möglich, den genauen Typ einer Klasseninstanz zu bestimmen;
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 demonstriert die Möglichkeit, mithilfe des Schlüsselworts [extends] von einer Klasse zu erben.
Zunächst verschieben wir die Klasse [Person] in ein Modul namens [Person.js]:
// classe
class Personne {
// constructeur
constructor(nom, prénom, âge) {
this.nom = nom;
this.prénom = prénom;
this.âge = âge;
}
// getters et setters
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 en JSON
toString() {
return JSON.stringify(this);
}
}
// export classe
export default Personne;
- Zeile 39: Wir exportieren die Klasse [Person], damit Skripte sie importieren können;
Das Skript [class-02] erstellt eine Klasse [Teacher], die von der Klasse [Person] abgeleitet ist:
// imports
import Personne from './Personne';
// classe
class Enseignant extends Personne {
// constructeur
constructor(nom, prénom, âge, discipline) {
super(nom, prénom, âge);
this.discipline = discipline;
}
// getters et setters
get discipline() {
return this._discipline;
}
set discipline(value) {
this._discipline = value;
}
}
// appel de la classe
function main() {
const enseignant = new Enseignant("Poirot", "Hercule", 66, "détective");
console.log("enseignant=", enseignant.toString(), typeof (enseignant), enseignant instanceof Enseignant);
}
// appel de main
main();
Kommentare
- Zeile 2: Wir importieren die Klasse [Person] aus dem Modul [Person.js], das sich im selben Ordner wie [class-02] befindet;
- Zeile 5: Die Klasse [Teacher] erweitert (erbt von) die Klasse [Person] mithilfe des Schlüsselworts [extends]: Sie fügt eine Eigenschaft [_subject] mit den entsprechenden Getter- und Setter-Methoden hinzu;
- Zeilen 8–11: Der Konstruktor der Klasse [Teacher] erhält vier Werte, um die vier Eigenschaften der Klasse zu initialisieren;
- Zeile 9: Das Schlüsselwort [super] ruft den Konstruktor der übergeordneten Klasse [Person] auf, der somit die Eigenschaften [_last_name, _first_name, _age] initialisiert;
- Zeile 10: Die zur Klasse [Teacher] gehörende Eigenschaft [_discipline] wird initialisiert;
- Zeilen 14–19: die Getter- und Setter-Methoden für die Eigenschaft [_discipline];
- Zeile 25: Es wird ein Objekt vom Typ [Teacher] erstellt;
- Zeile 26: Wir verwenden die Methode [teacher.toString()]. Die Klasse [Teacher] verfügt nicht über diese Methode. Daher wird automatisch die Methode aus der übergeordneten Klasse verwendet. Diese Methode rendert den Ausdruck [JSON.stringify(this)], wobei [this] hier ein [Teacher]-Objekt ist, kein [Person]-Objekt. Dies wird in der objektorientierten Programmierung als Klassenpolymorphismus bezeichnet. Ein großes Wort für JavaScript, das keine objektorientierte Sprache ist. Dennoch tut JavaScript hier das, was von ihm erwartet wird: Es zeigt einen Lehrer korrekt 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 [teacher] vom Typ [Teacher] ist;
13.4. Skript [class-03]
Das Skript [class-03] zeigt, dass eine Unterklasse Eigenschaften und Methoden ihrer Oberklasse überschreiben kann. Hier überschreiben wir die Methode [toString] der Oberklasse:
// imports
import Personne from './Personne';
// classe
class Enseignant extends Personne {
// constructeur
constructor(nom, prénom, âge, discipline) {
super(nom, prénom, âge);
this.discipline = discipline;
}
// getters et setters
get discipline() {
return this._discipline;
}
set discipline(value) {
this._discipline = value;
}
// redéfinition de toString
toString() {
return "[Enseignant]" + JSON.stringify(this);
}
}
// appel de la classe
function main() {
const enseignant = new Enseignant("Poirot", "Hercule", 66, "détective");
console.log("enseignant=", enseignant.toString(), typeof (enseignant), enseignant instanceof Enseignant);
}
// appel de 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] demonstriert erneut Polymorphismus in der Praxis: Wenn eine Funktion einen formalen Parameter vom Typ [Person] erwartet, können wir einen abgeleiteten Typ wie [Teacher] übergeben. Tatsächlich verfügt der Typ [Teacher] aufgrund der Ableitung über alle Attribute des Typs [Person].
Zunächst isolieren wir den Typ [Teacher] in einem Modul [Teacher.js]:
// imports
import Personne from './Personne';
// classe
class Enseignant extends Personne {
// constructeur
constructor(nom, prénom, âge, discipline) {
super(nom, prénom, âge);
this.discipline = discipline;
}
// getters et setters
get discipline() {
return this._discipline;
}
set discipline(value) {
this._discipline = value;
}
}
// export classe
export default Enseignant;
- Zeile 24: Die Klasse [Teacher] wird exportiert, damit andere Skripte sie importieren können;
Das Skript [class-04] lautet wie folgt:
// imports
import Enseignant from './Enseignant';
import Personne from './Personne';
// fonction acceptant une personne comme paramètre
function show(personne) {
// dans tous les cas
console.log("paramètre=", personne.toString(), typeof (personne));
// instance de Personne
if (personne instanceof Personne) {
console.log("personne=", personne.toString());
}
// instance de Enseignant
if (personne instanceof Enseignant) {
console.log("enseignant=", personne.toString());
}
}
// appel de show avec un enseignant
show(new Enseignant("Poirot", "Hercule", 66, "détective"));
show(new Personne("Marple", "Miss", 70));
- Zeile 6: Die Funktion [show] erwartet einen Typ [Person] oder einen davon abgeleiteten Typ;
- Zeile 8: Die Zeichenkette des Parameters und sein Typ werden angezeigt. Wir finden [object];
- Zeilen 10–16: Wir können feststellen, ob es sich um einen Typ [Person] oder einen Typ [Teacher] handelt. Der Code kann daher an den tatsächlichen Typ des Parameters angepasst werden;
Die Ausführungsergebnisse 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;