TypeScript
Klassen
Suche…
Einführung
TypeScript unterstützt wie ECMA Script 6 die objektorientierte Programmierung mit Klassen. Dies steht im Gegensatz zu älteren JavaScript-Versionen, die nur prototypbasierte Vererbungskette unterstützen.
Die Klassenunterstützung in TypeScript ähnelt der von Sprachen wie Java und C #, da Klassen von anderen Klassen erben können, während Objekte als Klasseninstanzen instanziiert werden.
Ähnlich wie diese Sprachen können TypeScript-Klassen Schnittstellen implementieren oder Generics verwenden.
Einfache Klasse
class Car {
public position: number = 0;
private speed: number = 42;
move() {
this.position += this.speed;
}
}
In diesem Beispiel deklarieren wir eine einfache Klasse Car
. Die Klasse besteht aus drei Mitgliedern: ein Privateigentum speed
, eine öffentliche Eigenschaft position
und eine öffentliche Methode move
. Beachten Sie, dass jedes Mitglied standardmäßig öffentlich ist. Deshalb ist move()
öffentlich, auch wenn wir das Schlüsselwort public
nicht verwendet haben.
var car = new Car(); // create an instance of Car
car.move(); // call a method
console.log(car.position); // access a public property
Grundvererbung
class Car {
public position: number = 0;
protected speed: number = 42;
move() {
this.position += this.speed;
}
}
class SelfDrivingCar extends Car {
move() {
// start moving around :-)
super.move();
super.move();
}
}
Dieses Beispiel zeigt , wie eine sehr einfache Unterklasse der erstellen Car
- Klasse des extends
Schlüsselwort. Die SelfDrivingCar
Klasse überschreibt die move()
Methode und verwendet die Implementierung der Basisklasse mit super
.
Konstrukteure
In diesem Beispiel verwenden wir den constructor
eine öffentliche Eigenschaft zu erklären position
und eine geschützte Eigenschaft speed
in der Basisklasse. Diese Eigenschaften werden als Parametereigenschaften bezeichnet . Sie lassen uns einen Konstruktorparameter und ein Member an einer Stelle deklarieren.
Eines der besten Dinge in TypeScript ist die automatische Zuweisung von Konstruktorparametern an die entsprechende Eigenschaft.
class Car {
public position: number;
protected speed: number;
constructor(position: number, speed: number) {
this.position = position;
this.speed = speed;
}
move() {
this.position += this.speed;
}
}
Der gesamte Code kann in einem einzigen Konstruktor fortgesetzt werden:
class Car {
constructor(public position: number, protected speed: number) {}
move() {
this.position += this.speed;
}
}
Beide werden mit gleichem Ergebnis von TypeScript (Entwurfszeit und Kompilierzeit) nach JavaScript übertragen, wobei jedoch deutlich weniger Code geschrieben wird:
var Car = (function () {
function Car(position, speed) {
this.position = position;
this.speed = speed;
}
Car.prototype.move = function () {
this.position += this.speed;
};
return Car;
}());
Konstruktoren abgeleiteter Klassen müssen den Basisklassenkonstruktor mit super()
aufrufen.
class SelfDrivingCar extends Car {
constructor(startAutoPilot: boolean) {
super(0, 42);
if (startAutoPilot) {
this.move();
}
}
}
let car = new SelfDrivingCar(true);
console.log(car.position); // access the public property position
Accessoren
In diesem Beispiel ändern wir das Beispiel "Einfache Klasse", um den Zugriff auf die speed
zu ermöglichen. Mit typecript-Accessoren können wir zusätzlichen Code in Gettern oder Setters hinzufügen.
class Car {
public position: number = 0;
private _speed: number = 42;
private _MAX_SPEED = 100
move() {
this.position += this._speed;
}
get speed(): number {
return this._speed;
}
set speed(value: number) {
this._speed = Math.min(value, this._MAX_SPEED);
}
}
let car = new Car();
car.speed = 120;
console.log(car.speed); // 100
Abstrakte Klassen
abstract class Machine {
constructor(public manufacturer: string) {
}
// An abstract class can define methods of it's own, or...
summary(): string {
return `${this.manufacturer} makes this machine.`;
}
// Require inheriting classes to implement methods
abstract moreInfo(): string;
}
class Car extends Machine {
constructor(manufacturer: string, public position: number, protected speed: number) {
super(manufacturer);
}
move() {
this.position += this.speed;
}
moreInfo() {
return `This is a car located at ${this.position} and going ${this.speed}mph!`;
}
}
let myCar = new Car("Konda", 10, 70);
myCar.move(); // position is now 80
console.log(myCar.summary()); // prints "Konda makes this machine."
console.log(myCar.moreInfo()); // prints "This is a car located at 80 and going 70mph!"
Abstrakte Klassen sind Basisklassen, von denen andere Klassen ausgehen können. Sie können nicht selbst instanziiert werden (dh Sie können keine new Machine("Konda")
erstellen).
Die zwei Hauptmerkmale einer abstrakten Klasse in Typescript sind:
- Sie können eigene Methoden implementieren.
- Sie können Methoden definieren, die erben Klassen implementieren müssen .
Aus diesem Grund können abstrakte Klassen konzeptionell als Kombination aus einer Schnittstelle und einer Klasse betrachtet werden .
Affe patchen eine Funktion in eine vorhandene Klasse
Manchmal ist es nützlich, eine Klasse um neue Funktionen erweitern zu können. Nehmen wir zum Beispiel an, dass ein String in einen Camel-Case-String konvertiert werden soll. Daher müssen wir TypeScript mitteilen, dass String
eine Funktion namens toCamelCase
, die einen string
zurückgibt.
interface String {
toCamelCase(): string;
}
Jetzt können wir diese Funktion in die String
Implementierung implementieren.
String.prototype.toCamelCase = function() : string {
return this.replace(/[^a-z ]/ig, '')
.replace(/(?:^\w|[A-Z]|\b\w|\s+)/g, (match: any, index: number) => {
return +match === 0 ? "" : match[index === 0 ? 'toLowerCase' : 'toUpperCase']();
});
}
Wenn diese Erweiterung von String
geladen ist, kann sie folgendermaßen verwendet werden:
"This is an example".toCamelCase(); // => "thisIsAnExample"
Transpilation
Bei einer Klasse SomeClass
wir, wie das TypeScript in JavaScript umgesetzt wird.
TypeScript-Quelle
class SomeClass {
public static SomeStaticValue: string = "hello";
public someMemberValue: number = 15;
private somePrivateValue: boolean = false;
constructor () {
SomeClass.SomeStaticValue = SomeClass.getGoodbye();
this.someMemberValue = this.getFortyTwo();
this.somePrivateValue = this.getTrue();
}
public static getGoodbye(): string {
return "goodbye!";
}
public getFortyTwo(): number {
return 42;
}
private getTrue(): boolean {
return true;
}
}
JavaScript-Quelle
Bei der Verwendung von TypeScript v2.2.2
die Ausgabe folgendermaßen aus:
var SomeClass = (function () {
function SomeClass() {
this.someMemberValue = 15;
this.somePrivateValue = false;
SomeClass.SomeStaticValue = SomeClass.getGoodbye();
this.someMemberValue = this.getFortyTwo();
this.somePrivateValue = this.getTrue();
}
SomeClass.getGoodbye = function () {
return "goodbye!";
};
SomeClass.prototype.getFortyTwo = function () {
return 42;
};
SomeClass.prototype.getTrue = function () {
return true;
};
return SomeClass;
}());
SomeClass.SomeStaticValue = "hello";
Beobachtungen
- Die Modifikation des Prototyps der Klasse ist in einem IIFE eingeschlossen .
- Membervariablen sind innerhalb der Hauptklasse definiert
function
. - Statische Eigenschaften werden direkt zum Klassenobjekt hinzugefügt, während Instanzeigenschaften zum Prototyp hinzugefügt werden.