Étendre ou implémenter une classe abstraite pure dans TypeScript

Supposons que j’ai une classe abstraite pure (c’est-à-dire une classe abstraite sans implémentation):

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

Comme en C # et Java, je peux étendre la classe abstraite:

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

Mais contrairement à C # et Java, je peux également implémenter la classe abstract:

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

Comment les classes B et C se comportent-elles différemment? Pourquoi devrais-je choisir l’un contre l’autre?

(Actuellement, le manuel TypeScript et la spécification de langage ne couvrent pas les classes abstraites.)

Le mot-clé implements traite la classe A comme une interface, ce qui signifie que C doit implémenter toutes les méthodes définies dans A , peu importe si elles ont une implémentation ou non dans A. Il n’y a pas non plus d’appels aux méthodes super en C.

extend se comporte plus comme ce que vous attendez du mot-clé. Vous devez implémenter uniquement les méthodes abstraites, et les super-appels sont disponibles / générés.

Je suppose que dans le cas des méthodes abstraites, cela ne fait aucune différence. Mais vous avez rarement une classe avec uniquement des méthodes abstraites, si vous le faites, il serait préférable de la transformer en une interface .

Vous pouvez facilement voir cela en regardant le code généré. J’ai fait un exemple de terrain de jeu ici .

En s’appuyant sur la réponse de @ toskv , si vous étendez une classe abstraite, vous devez appeler super() dans le constructeur de la sous-classe. Si vous implémentez la classe abstract, vous n’avez pas à appeler super() (mais vous devez implémenter toutes les méthodes déclarées dans la classe abstract, y compris les méthodes privées).

Implémenter une classe abstraite au lieu de l’étendre pourrait être utile si vous voulez créer une classe fictive pour le test sans avoir à vous soucier des dépendances et du constructeur de la classe d’origine.

J’ai été conduit ici parce que je venais de me poser la même question et, en lisant les réponses, il m’est venu à l’esprit que le choix affecterait également l’opérateur instanceof .

Comme une classe abstraite est une valeur réelle qui est émise vers JS, elle peut être utilisée pour les vérifications à l’exécution lorsqu’une sous-classe l’étend.

 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 

Dans l’exemple des extensions, vous ne donnez rien de nouveau à la classe. Donc, il n’est prolongé par rien. Bien que l’extension par rien soit valide, Typescript, il me semble que dans ce cas, les «outils» seraient plus appropriés. Mais au bout du compte, ils sont équivalents.