Interfaces (interface keyword, Duck-Typing usw.)

Mat

Aktives Mitglied
Interfaces sind in JS recht umständlich emulierbar. Und die erscheinen mir auch eher sinnlos, weil es je nach Einsatzzweck viele weniger umständliche Techniken gibt (Mixins, Methoden-Borrowing, Kopierkonstruktoren, dynamisch generierte Funktionen, ein reines Methoden-Objekt usw).

Ich hatte trotzdem versucht, das per Hand zu implementieren, aber am Ende kam stattdessen eher eine Abstrakte Klasse raus :D

Habe dann aber noch gesehen, dass es schon die Keywords "Interface" und "implements" gibt. Bei anderen OO-Keywords wie zB class arbeitet er im Hintergrund mit dem prototype-Attribut.

Wollte aus Neugier mal ausprobieren, was was er bei interface und implements im Hintergrund macht, aber bei dem Code kommt in NodeJS 14.X ein Syntaxfehler (schon Zeile 1).

Javascript:
interface IBelle     { bellen(); }
/*
interface IBelle {
              ^^^^^^
SyntaxError: Unexpected identifier
*/
interface IBuddle     { buddeln();}

class Hund implements IBelle, IBuddle {
    constructor(name) { this.name = name; }

    bellen() {
        console.log(`Mein Name ist ${this.name} und ich möchte hier bellen`);
    }
}

const rex = new Hund('Rex');

try {
    rex.bellen();
} catch (error) {
    console.error(error.message);
}

try {
    rex.buddeln();
} catch (error) {
    console.error(error.message);
}

Welche Runtime unterstützt die Ausführung? Oder geht sowas derzeit nur mit externen Bibliotheken?

Hier noch ein früherer Versuch (nicht ganz fertig). Sollte in Richtung DuckTyping gehen, allerdings wurde das dann eine Mischung aus einem Klassengenerator und einer Abstrakten Klasse, also am Ziel vorbei:
Javascript:
const Interfaces = {
    initialisiere: function (interfaceTyp) {
        if (!interfaceTyp.METHODEN) return;
        for (const methode of interfaceTyp.METHODEN) {
            interfaceTyp.prototype[methode] = function () {
                throw new Error(`${interfaceTyp.name}.${methode} nicht implementiert!`);
            }
        }
    },
    allesImplementiert: function (objekt, interfaceTyp) {
        if (interfaceTyp.size < 1 || !interfaceTyp.METHODEN) return;
        for (const methode of interfaceTyp.METHODEN) {
            if (!objekt.hasOwnProperty(methode) || (typeof objekt[methode] !== 'function')) {
                return false;
            }
        }
        return true;
    }
};

class IHund {
    static METHODEN = ['bellen', 'buddeln'];
}

Interfaces.initialisiere(IHund);

class Hund extends IHund {
    constructor(name) {
        super();
        this.name = name;
    }

    bellen() {
        console.log(`Mein Name ist ${this.name} und ich möchte hier bellen`);
    }
}

const rex = new Hund('Rex');
console.log(Interfaces.allesImplementiert(rex, IHund)); // false

try {
    rex.bellen();
} catch (error) {
    console.error(error.message);
}

try {
    rex.buddeln();
} catch (error) {
    console.error(error.message);
}
 
Zuletzt bearbeitet:
Die Schlüsselwörter sind nur reserviert, haben aber keine Funktion. So war auch class reserviert, lange bevor überhaupt die Rede von Klassen in ES6 war. (fun fact an der Stelle: Auch Java hat goto reserviert, wurde aber nie implementiert)
Nutzen kannst du sie also nirgendwo. Außer eben z. B. in TypeScript.

Aber allgemein zu dem Thema: Ich arbeite schon einige Jahre und sehr viel in JavaScript (jetzt TypeScript), aber ich bin vor allem in letzter Zeit nicht in die Versuchung gekommen, solch Konstrukte in JS zu implementieren oder zu verwenden. Ich hab mit der Zeit gelernt, Dinge nicht zu sehr zu verkomplizieren und auch die Nachteile von Klassen im Allgemeinen. Mehr als Funktionen (+ higher order functions und Objekt-Factory-Funktionen) und Datenobjekte brauch ich so gut wie nie - selbstverständlich jetzt im Kontext von ES-Modulen. Und das Betrifft Server in Node sowie Front-End-Entwicklung im Browser.
Gut möglich, dass es da draußen einige Pattern gibt, die ich nicht verwende, ich aber doch ganz hilfreich finden würde. Aber Klassen im Speziellen sind jetzt auch nicht super idiomatisch in JS.
 
Zurück
Oben Unten