web-dev-qa-db-fra.com

Quelle est la différence entre 'extend' et 'implements' dans TypeScript

J'aimerais savoir ce quemanetenfantont en commun et en quoi ils diffèrent.

class Person {
  name: string;
  age: number;
}
class child extends Person {}
class man implements Person {}
49
davejoem

Version courte

  • extends signifie: 

La classe new est un enfant. Cela procure des avantages avec l'héritage. Il a toutes les propriétés, méthodes en tant que parent. Il peut en remplacer certains et en implémenter de nouveaux, mais le composant parent est déjà inclus.

  • implements signifie:

La nouvelle classe peut être traitée comme la même "forme", alors que ce n'est pas un enfant. Il pourrait être passé à n'importe quelle méthode où la Person est requise, même si le parent est différent de Person.

Plus ...

Dans OOP(langages comme C #, Java), nous utiliserions 

extends pour bénéficier de l'héritage (voir wiki ). Petite cite: 

... Dans la plupart des langages orientés objet basés sur des classes, l'héritage est un mécanisme dans lequel un objet acquiert toutes les propriétés et tous les comportements de l'objet parent. L'héritage permet aux programmeurs de: créer des classes construites à partir de classes existantes ...

implements sera plus pour le polymorphisme (voir wiki ). Petite cite:

... le polymorphisme est la fourniture d'une interface unique à des entités de types différents ...

Nous pouvons donc avoir un arbre d'héritage vraiment différent de notre class Man

class Man extends Human ...

mais si nous déclarons aussi que nous pouvons prétendre être d'un type différent - Person:

class Man extends Human 
          implements Person ...

.. alors nous pouvons l'utiliser n'importe où, où la Person est requise. Nous devons simplement remplir le "interface"de Persons (c'est-à-dire mettre en œuvre tous ses éléments publics).

implement autre classe? C'est vraiment cool

Javascript Nice face (un des avantages) est le support intégré de la frappe Duck ( voir wiki ). Petite cite:

"Si ça marche comme un canard et que ça crie comme un canard, alors ça doit être un canard."

Ainsi, en Javascript, si deux objets différents ... ont une méthode similaire (par exemple render()), ils peuvent être transmis à une fonction qui l’attend:

function(engine){
  engine.render() // any type implementing render() can be passed
}

Pour ne pas perdre cela - nous pouvons faire la même chose avec TypeScript - avec davantage de support typé. Et c'est là 

class implements class

a son rôle, où il est logique

En OOP langues sous la forme C# ... impossible de le faire ...

La documentation devrait également aider ici:

Interfaces Extending Classes

Lorsqu'un type d'interface étend un type de classe, il hérite des membres de la classe mais pas leurs implémentations. C'est comme si l'interface avait a déclaré tous les membres de la classe sans fournir un la mise en oeuvre. Les interfaces héritent même du privé et des protégés membres d'une classe de base. Cela signifie que lorsque vous créez une interface qui étend une classe avec des membres privés ou protégés, cette interface type ne peut être implémenté que par cette classe ou une sous-classe de celle-ci.

Ceci est utile lorsque vous avez une grande hiérarchie d'héritage, mais que vous voulez pour spécifier que votre code ne fonctionne qu'avec les sous-classes qui ont certains Propriétés. Il n’est pas nécessaire que les sous-classes soient associées à part hériter de la classe de base. Par exemple:

class Control {
    private state: any;
}

interface SelectableControl extends Control {
    select(): void;
}

class Button extends Control {
    select() { }
}

class TextBox extends Control {
    select() { }
}

class Image extends Control {
}

class Location {
    select() { }
}

Donc pendant 

  • extends signifie - il obtient tout de son parent 
  • implements dans ce cas est presque comme implémenter une interface. Un objet enfant peut prétendre qu'il est parent ... mais il ne reçoit aucune implémentation
61
Radim Köhler

Dans TypeScript (et quelques autres langages OO), vous avez des classes et des interfaces. 

Une interface n'a pas d'implémentation, c'est juste un "contrat" ​​de ce que les membres/méthodes de ce type ont.
Par exemple:

interface Point {
    x: number;
    y: number;
    distance(other: Point): number;
}

Les instances qui implémentent cette interface Point doivent avoir deux membres de type numéro: x et y et une méthode distance qui reçoit une autre instance Point et renvoie une number.
L'interface n'implémente aucun de ceux-ci.

Les classes sont les implémentations:

class PointImplementation implements Point {
    public x: number;
    public y: number;

    constructor(x: number, y: number) {
        this.x = x;
        this.y = y;
    }

    public distance(other: Point): number {
        return Math.sqrt(Math.pow(this.x - other.x, 2) + Math.pow(this.y - other.y, 2));
    }
}

( code dans la cour de récréation )

Dans votre exemple, vous traitez votre classe Person une fois comme une classe lorsque vous l'étendez et une fois comme une interface lorsque vous l'implémentez.
Votre code:

class Person {
    name: string;
    age: number;
}
class Child  extends Person {}

class Man implements Person {}

A une erreur de compilation en disant:

La classe 'Man' n'implémente pas correctement l'interface 'Person'.
La propriété 'nom' est manquante dans le type 'Man'.

Et c'est parce que les interfaces manquent d'implémentation.
Donc, si vous implement une classe, vous ne prenez que son "contrat" ​​sans l'implémentation, vous devrez donc procéder comme suit:

class NoErrorMan implements Person {
    name: string;
    age: number;
}

( code dans la cour de récréation )

En bout de ligne, dans la plupart des cas, vous voulez extend une autre classe et non implement.

54
Nitzan Tomer

Super réponse de @ nitzan-tomer! M'a beaucoup aidé ... J'ai prolongé un peu sa démo avec:

IPoint interface;
Point implements IPoint;
Point3D extends Point;

Et comment ils se comportent dans les fonctions attendant un type IPoint. 

Donc, ce que j’ai appris jusqu’à présent et que j’utilise comme règle empirique: si vous utilisez des classes et des méthodes qui attendent des types génériques, utilisez les interfaces comme types attendus. Et assurez-vous que le parent ou la classe de base utilise cette interface. De cette façon, vous pouvez utiliser toutes les sous-classes dans la mesure où elles implémentent l'interface.

Hier the Demo Extended

3
andzep
  1. Interface étend l'interface avec la forme
  2. L'interface étend la classe avec la forme
  3. L'interface implémentation de classe doit implémenter tous les champs fournis par l'interface
  4. La classe implémente la classe avec la forme
  5. La classe étend la classe avec tous les champs

extends se concentre sur hériter et implements se concentre sur la contrainte, qu'il s'agisse d'interfaces ou de classes.

0
lilei