Vraag Wat is het verschil tussen 'extends' en 'implements' in TypeScript


Ik zou graag willen weten wat man en kind hebben gemeen en hoe ze verschillen.

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

29
2017-08-08 16:49


oorsprong


antwoorden:


Verkorte versie

  • extends middelen:

De nieuwe klasse is een kind. Het krijgt voordelen die met overerving komen. Het heeft alle eigenschappen, methoden als zijn ouder. Het kan sommige hiervan overschrijven en nieuw implementeren, maar de bovenliggende dingen zijn al inbegrepen.

  • implements middelen:

De nieuwe klas kan worden behandeld als hetzelfde "vorm", terwijl het is geen kind. Het kan worden doorgegeven aan elke methode waarbij de Person is vereist, ongeacht of er een andere bovenliggende dan is Person

Meer ...

In OOP  (talen zoals C #, Java) we zouden gebruiken

extends profiteren van erfenis (zie wiki). Klein cite:

... Overerving in de meeste op klassen gebaseerde objectgeoriënteerde talen is een mechanisme waarbij een object alle eigenschappen en het gedrag van het bovenliggende object verkrijgt. Met overerving kunnen programmeurs: klassen maken die zijn gebaseerd op bestaande klassen ...

implements zal meer zijn voor polymorfisme (zie wiki). Klein cite:

... polymorfisme is het verschaffen van een enkele interface voor entiteiten van verschillende typen ...

Dus we kunnen een heel andere overervingsboom van ons hebben class Man.

class Man extends Human ...

maar als we ook verklaren dat we ons kunnen voordoen als een ander type - Person:

class Man extends Human 
          implements Person ...

.. dan kunnen we het overal gebruiken, waar de Person Is benodigd. We moeten gewoon Personen vervullen "interface"  (d.w.z. implementeer al zijn publieke zaken).

implement andere klas? Dat is echt cool spul

Javascript leuk gezicht (een van de voordelen) is de ingebouwde ondersteuning van het typen van de eend (zie wiki). Klein cite:

"Als het als een eend loopt en het kwaakt als een eend, dan moet het een eend zijn."

Dus, in Javascript, als twee verschillende objecten ... dezelfde methode zouden hebben (B.v. render()) ze kunnen worden doorgegeven aan een functie die dit verwacht:

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

Om dat niet te verliezen - we kunnen in Typescript hetzelfde doen - met meer getypte ondersteuning. En dat is waar

class implements class

heeft zijn rol, waar het zinvol is

In OOP-talen als C# ... geen manier om dat te doen ...

Ook de documentatie zou hier moeten helpen:

Interfaces uitbreiding van klassen

Wanneer een interfacetype een klassentype uitbreidt, neemt het de leden van over   de klasse, maar niet de implementaties. Het is alsof de interface dat had   verklaarde alle leden van de klas zonder een   implementatie. Interfaces erven zelfs het private en beschermde   leden van een basisklasse. Dit betekent dat wanneer u een interface aanmaakt   die een klasse uitbreidt met privé of beschermde leden, die interface   type kan alleen worden geïmplementeerd door die klasse of een subklasse ervan.

Dit is handig als u een grote overervingshiërarchie heeft, maar wel wilt   om aan te geven dat uw code werkt met alleen bepaalde subklassen   eigenschappen. De subklassen hoeven niet afhankelijk te zijn van overerving   van de basisklasse. Bijvoorbeeld:

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() { }
}

Dus terwijl

  • extends betekent - het komt allemaal van zijn ouder
  • implements in dit geval is het bijna alsof je een interface implementeert. Een kinderobject kan doen alsof het bovenliggend is ... maar het krijgt geen implementatie

35
2017-08-08 17:13



In typoscript (en enkele andere OO-talen) heb je klassen en interfaces.

Een interface heeft geen implementatie, het is slechts een "contract" van wat leden / methode van dit type heeft.
Bijvoorbeeld:

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

Instanties die dit implementeren Point interface moet twee leden van typenummer hebben: x en yen een methode distance die een andere ontvangt Point exemplaar en geeft a number.
De interface implementeert geen van die.

Klassen zijn de implementaties:

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 in de speeltuin)

In uw voorbeeld behandelt u uw Person classeer eens als een klasse wanneer je het uitbreidt en een keer als een interface wanneer je het implementeert.
Jouw code:

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

class Man implements Person {}

Heeft een compilatiefout:

Klasse 'Man' implementeert ten onrechte interface 'Persoon'.
  Property 'name' ontbreekt in type 'Man'.

En dat komt omdat interfaces de implementatie missen.
Dus als je implement een klasse, dan neem je alleen zijn "contract" zonder de implementatie, dus je moet dit doen:

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

(code in de speeltuin)

Waar het op neerkomt, is dat u in de meeste gevallen wilt extend een andere klasse en niet om implement het.


36
2017-08-08 17:14



Geweldig antwoord van @ nitzan-tomer! Heeft me veel geholpen ... Ik heb zijn demo een beetje uitgebreid met:

IPoint interface;
Point implements IPoint;
Point3D extends Point;

En hoe ze zich gedragen in functies die een IPoint-type verwachten.

Dus wat ik tot nu toe heb geleerd en gebruik als een duimregel: als je klassen en methoden gebruikt die algemene typen verwachten, gebruik dan interfaces als de verwachte typen. En zorg ervoor dat de ouder of basisklasse die interface gebruikt. Op die manier kun je alle subklassen daar gebruiken voor zover ze de interface implementeren.

Hier de uitgebreide demo


2
2017-12-01 14:36