Historie des Themas
Viele streng typisierte Sprachen (C++, C#, Python) erlauben eine explizite Beschreibung von Überladungen für Operatoren (z. B. +, -, *, ==) auf Klassenebene. In TypeScript, wie auch in JavaScript, fehlt die Operatorüberladung aus historischen und architektonischen Gründen.
Problem
Wenn Unterstützung für arithmetische oder andere Operationen für komplexe Typen (z. B. komplexe Zahlen oder Vektoren) hinzugefügt werden muss, ist es nicht möglich, die Standardoperatoren zu ändern. Dies schränkt die Ausdruckskraft ein und erfordert das Erfinden von Umgehungsmustern.
Lösung
In TypeScript wird die Operatorüberladung durch speziell benannte Methoden (z. B. add, equals, multiply) imitiert. Wenn wir eine Klasse mit solchen Methoden ausstatten, implementieren wir ein typensicheres Verhalten, obwohl die Syntax nicht so prägnant ist wie in C++.
Beispielcode:
class Vector { constructor(public x: number, public y: number) {} add(other: Vector): Vector { return new Vector(this.x + other.x, this.y + other.y); } equals(other: Vector): boolean { return this.x === other.x && this.y === other.y; } } const a = new Vector(1, 2); const b = new Vector(3, 4); const c = a.add(b); // Vector { x: 4, y: 6 } const eq = a.equals(b); // false
Wesentliche Merkmale:
Kann das Verhalten des Operators "==" oder "+" für eine eigene Klasse in TypeScript überschrieben werden?
Nein, JavaScript (und TypeScript) erlaubt nicht das direkte Überladen von Standardoperatoren für benutzerdefinierte Objekte. Operatoren funktionieren streng nach dem Standard für Object, Number und andere Primitives. Jeder Versuch einer solchen "Überladung" führt zu unkorrektem oder unerwartetem Verhalten oder funktioniert einfach nicht.
Kann valueOf oder toString verwendet werden, um indirekt auf Operatoren einzuwirken?
In einigen Fällen kann valueOf verwendet werden (z. B. für eine kurze Umwandlung in eine Zahl), aber nur für Operatoren, die auf den primitiven Wert des Objekts zugreifen.
class Box { constructor(private v: number) {} valueOf() { return this.v; } } const a = new Box(10); console.log(a + 5); // 15 — funktioniert, aber für komplexe Objekte ist es gegenintuitiv
Für komplexe Strukturen und logische Operatoren ist es jedoch sinnvoll, explizite Methoden zu verwenden.
Gibt es Pläne, die Operatorüberladung in TypeScript oder ECMAScript hinzuzufügen?
Derzeit gibt es keine bestätigten Pläne: Prinzipiell widerspricht die Operatorüberladung dem Design von JS, da sie das Verhalten der Standardobjekte erheblich ändern und zu Instabilität im Code führen könnte.
Ein Entwickler erstellt eine Klasse Matrix, in der valueOf/toString für den Einsatz in mathematischen Ausdrücken implementiert wird. Bei der Addition mit Zahlen oder Strings entstehen unvorhersehbare Ergebnisse, strenge Typisierung ist nicht möglich.
Vorteile:
Nachteile:
Die Klasse Vector implementiert Methoden add, multiply, equals mit klarer Typisierung der Eingabe- und Ausgabeparameter. Die Klienten der Klasse verwenden explizit die entsprechenden Methoden, die Semantik bleibt erhalten und die strenge Typisierung ist gewährleistet.
Vorteile:
Nachteile: