2016-03-14 5 views
27

nehme ich eine reine abstrakte Klasse haben (das heißt, eine abstrakte Klasse ohne Implementierung):Erweiterung gegen eine reine abstrakte Klasse in Typoskript Umsetzung

abstract class A { 
    abstract m(): void; 
} 

Wie in C# und Java, kann ich verlängern die abstrakte Klasse:

class B extends A { 
    m(): void { } 
} 

Aber im Gegensatz zu in C# und Java, kann ich auch die abstrakte Klasse implementieren:

class C implements A { 
    m(): void { } 
} 

Wie Klassen B und C anders verhalten? Warum sollte ich eins gegen das andere wählen?

(Derzeit ist die Typoskript handbook und language specification nicht abstrakte Klassen abdecken.)

+0

Es gibt jetzt einen Abschnitt über abstrakte Klassen im TypeScript-Handbuch. https://www.typescriptlang.org/docs/handbook/classes.html Danke für diese Frage! Ich hatte keine Ahnung, dass "abstract" in TS verfügbar war und das hat mir geholfen, es zu verstehen. – theUtherSide

Antwort

33

Die Schlüsselwort implementiert behandelt die A-Klasse als eine Schnittstelle, das heißt C alle Methoden in A definiert umzusetzen hat, egal ob sie eine Implementierung haben oder nicht in A. Es gibt auch keine Aufrufe von Super-Methoden in C.

erweitert verhält sich mehr wie Sie von dem Schlüsselwort erwarten würden. Sie müssen nur die abstrakten Methoden implementieren, und Superaufrufe sind verfügbar/generiert.

Ich denke, dass im Falle der abstrakten Methoden es keinen Unterschied macht. Aber Sie haben selten eine Klasse mit nur abstrakte Methoden, wenn Sie es tun, wäre es viel besser, nur in eine Schnittstelle zu transformieren.

Sie können dies leicht sehen, indem Sie den generierten Code betrachten. Ich habe ein Spielplatzbeispiel gemacht here.

+3

Wenn 'A' eine reine abstrakte Klasse ist, ist vielleicht der einzige beobachtbare Unterschied das Verhalten des Schlüsselworts 'instanceof'? Ich stimme zu, dass Interfaces wahrscheinlich reinen abstrakten Klassen vorzuziehen wären. In Angular 2 kann jedoch nur Letzteres als DI-Provider-Token verwendet werden. –

+1

In der Tat, danke für die Entdeckung der instanceof Sache, ich werde es der Antwort für die Fertigstellung hinzufügen (Sie können eine Änderung vornehmen, wenn Sie möchten). Was angular2 betrifft, ist das ein angular2-spezifisches Problem. :) – toskv

+0

@toskv, danke für die Beschreibung der Anwendbarkeit des Schlüsselwortes 'implements' zu Interfaces AND class. Zum Beispiel verwendet AngularJS 2.0 dies, um ihre "OnInit" CLASS (statt "Schnittstelle") zu implementieren. Ich habe mich umgesehen, hast du einen Hinweis darauf. Ich sehe es nicht klar in der TS-Dokumentation. – MoMo

0

Im Beispiel von extends, die Sie angeben, fügen Sie der Klasse nichts Neues hinzu. Es wird also um nichts erweitert. Obwohl die Erweiterung um nichts das gültige Typoskript ist, scheint es mir, dass in diesem Fall "implementiert" geeigneter wäre. Aber am Ende des Tages sind sie gleichwertig.

2

Aufbauend auf @toskv's answer, wenn Sie eine abstrakte Klasse erweitern , haben Sie super() in der Unterklasse Konstruktor aufrufen. Wenn Sie die abstrakte Klasse implementieren, müssen Sie nicht super() aufrufen (aber Sie müssen alle Methoden implementieren, die in der abstrakten Klasse deklariert sind, einschließlich privater Methoden).

Das Implementieren einer abstrakten Klasse anstelle einer Erweiterung könnte nützlich sein, wenn Sie eine Mock-Klasse zum Testen erstellen möchten, ohne sich um die Abhängigkeiten und den Konstruktor der ursprünglichen Klasse kümmern zu müssen.

0

Ich wurde hier geführt, weil ich gerade die selbe Frage gestellt hatte und während ich die Antworten las, kam es mir vor, dass die Wahl auch den instanceof Operator betrifft.

Da eine abstrakte Klasse ein tatsächlicher Wert ist, der an JS ausgegeben wird, kann sie für Laufzeitprüfungen verwendet werden, wenn eine Unterklasse sie erweitert.

abstract class A {} 

class B extends A {} 

class C implements A {} 

console.log(new B() instanceof A) // true 
console.log(new C() instanceof A) // false 
Verwandte Themen