Interfaces und Klassen sind zwei wichtige Konzepte in TypeScript, die helfen, den Code besser zu strukturieren und die Vorteile der objektorientierten Programmierung zu nutzen. In diesem Artikel werfen wir einen Blick darauf, was Interfaces und Klassen sind, wie sie funktionieren und welche Vorteile sie bieten.
Was sind Interfaces und wann sie verwendet werden?
Ein Interface in TypeScript ist eine Struktur, die den Vertrag für Objekte definiert. Es gibt an, welche Eigenschaften und Methoden ein Objekt haben muss, ohne deren genaue Implementierung festzulegen. Ein Interface wird oft verwendet, um Typen für Objekte zu definieren und sicherzustellen, dass verschiedene Objekte einem bestimmten Schema entsprechen.
Ein einfaches Beispiel eines Interfaces:
interface User {
id: number;
name: string;
email: string;
}
let user: User = {
id: 1,
name: "Philipp",
email: "philipp@example.com"
};
In diesem Beispiel gibt das Interface `User` vor, dass jedes Objekt vom Typ `User` die Eigenschaften `id`, `name` und `email` haben muss, und legt auch deren Typen fest. Interfaces bieten eine klare Struktur und können an vielen Stellen eingesetzt werden:
- Um sicherzustellen, dass Objekte eine bestimmte Struktur haben
- Um Parameter von Funktionen oder Rückgabewerte zu typisieren
- Um die Struktur von Klassen vorzugeben
Vererbung und Implementierung von Interfaces
TypeScript unterstützt Vererbung von Interfaces, was bedeutet, dass ein Interface auf einem anderen Interface basieren kann und dabei zusätzliche Eigenschaften hinzufügen kann. Dies ist nützlich, wenn es verschiedene Variationen von einem Objekt geben soll.
interface Person {
name: string;
age: number;
}
interface Employee extends Person {
employeeId: number;
}
let employee: Employee = {
name: "Sarah",
age: 30,
employeeId: 12345
};
Hier erweitert das `Employee`-Interface das `Person`-Interface und fügt die `employeeId`-Eigenschaft hinzu. Jedes Objekt vom Typ `Employee` muss also alle Eigenschaften von `Person` und `Employee` enthalten.
Ein Interface kann auch von einer Klasse implementiert werden. Das bedeutet, dass die Klasse alle im Interface definierten Eigenschaften und Methoden bereitstellen muss:
interface Printable {
print(): void;
}
class Document implements Printable {
print() {
console.log("Dokument wird gedruckt...");
}
}
let doc = new Document();
doc.print(); // Ausgabe: Dokument wird gedruckt...
In diesem Beispiel implementiert die Klasse `Document` das Interface `Printable`, was bedeutet, dass die Klasse eine `print`-Methode haben muss, wie im Interface definiert.
Klassen und ihre Vorteile gegenüber JavaScript
Klassen in TypeScript sind eine Erweiterung der Klassen aus JavaScript. Sie bieten eine einfache Möglichkeit, Objekte und deren Verhalten zu definieren und zu organisieren. TypeScript-Klassen ermöglichen es, durch Vererbung und den Einsatz von Konstruktoren und Modifikatoren (wie `public`, `private` und `protected`) komplexe Logik abzubilden.
Ein Beispiel einer TypeScript-Klasse:
class Person {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
greet() {
console.log(`Hallo, mein Name ist ${this.name} und ich bin ${this.age} Jahre alt.`);
}
}
let person = new Person("Philipp", 35);
person.greet(); // Ausgabe: Hallo, mein Name ist Philipp und ich bin 35 Jahre alt.
Einige Vorteile von TypeScript-Klassen im Vergleich zu reinem JavaScript:
- Statische Typisierung: TypeScript stellt sicher, dass die richtigen Typen für Klassenattribute verwendet werden.
- Modifikatoren: Attribute können als `public`, `private` oder `protected` markiert werden, um deren Zugänglichkeit zu steuern. Zum Beispiel:
class Person {
private name: string;
protected age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
Hier kann die Eigenschaft `name` nur innerhalb der Klasse verwendet werden, und die Eigenschaft `age` nur in der Klasse und den abgeleiteten Klassen. Klassen in TypeScript ermöglichen einfache Vererbung, was die Wiederverwendung von Code erleichtert.
Abstrakte Klassen und Interfaces im Vergleich
Sowohl abstrakte Klassen als auch Interfaces in TypeScript bieten die Möglichkeit, Strukturen für andere Klassen vorzugeben. Sie unterscheiden sich jedoch in ihrer Verwendung und ihren Fähigkeiten.
Interfaces:
- Definieren nur, welche Eigenschaften und Methoden ein Objekt oder eine Klasse haben muss, bieten aber keine konkrete Implementierung.
- Eine Klasse kann mehrere Interfaces implementieren, was eine flexible Codegestaltung ermöglicht.
Abstrakte Klassen:
- Können sowohl konkrete Implementierungen als auch abstrakte Methoden (ohne Implementierung) enthalten. Diese abstrakten Methoden müssen von den abgeleiteten Klassen implementiert werden.
- Eine Klasse kann nur eine abstrakte Klasse erben, was die Flexibilität im Vergleich zu Interfaces einschränkt.
Ein Beispiel einer abstrakten Klasse:
abstract class Animal {
abstract makeSound(): void;
move(): void {
console.log("Das Tier bewegt sich.");
}
}
class Dog extends Animal {
makeSound() {
console.log("Bellt");
}
}
let dog = new Dog();
dog.makeSound(); // Ausgabe: Bellt
dog.move(); // Ausgabe: Das Tier bewegt sich.
Hier definiert die abstrakte Klasse `Animal` eine abstrakte Methode `makeSound()`, die in den abgeleiteten Klassen implementiert werden muss. Abstrakte Klassen ermöglichen es, eine teilweise Implementierung anzubieten und die restliche Implementierung den abgeleiteten Klassen zu überlassen.
Fazit
Interfaces und Klassen sind mächtige Werkzeuge in TypeScript, um sauberen und gut strukturierten Code zu schreiben. Während Interfaces hauptsächlich dazu verwendet werden, Strukturen für Objekte und Klassen zu definieren, ermöglichen Klassen die Implementierung von Funktionen und Verhalten. Abstrakte Klassen bieten einen Mittelweg, indem sie Teile einer Implementierung vordefinieren, während der Rest von den abgeleiteten Klassen übernommen wird. Diese Konzepte machen TypeScript zu einer flexiblen und robusten Sprache für die Entwicklung von komplexen Anwendungen.