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:

  1. Sie können eigene Methoden implementieren.
  2. 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.


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow