Qual è la differenza tra "extends" e "implements" in TypeScript


Risposte:


153

Versione breve

  • extends si intende:

La nuova classe è un bambino . Ottiene vantaggi derivanti dall'eredità. Ha tutte le proprietà, i metodi come genitore. Può sovrascrivere alcuni di questi e implementarne di nuovi, ma il materiale genitore è già incluso.

  • implements si intende:

La nuova classe può essere trattata come la stessa "forma" , mentre non è un bambino . Potrebbe essere passato a qualsiasi metodo in cui Personè richiesto, indipendentemente dal fatto che abbia un genitore diverso daPerson

Di Più ...

In OOP (linguaggi come C #, Java) useremmo

extendstrarre profitto dall'eredità (vedi wiki ). Piccola citazione:

... L'ereditarietà nella maggior parte dei linguaggi orientati agli oggetti basati su classi è un meccanismo in cui un oggetto acquisisce tutte le proprietà e i comportamenti dell'oggetto genitore. L'ereditarietà consente ai programmatori di: creare classi basate su classi esistenti ...

implementssarà più per il polimorfismo (vedi wiki ). Piccola citazione:

... il polimorfismo è la fornitura di un'unica interfaccia per entità di diverso tipo ...

Quindi, possiamo avere un albero di eredità molto diverso dal nostro class Man.

class Man extends Human ...

ma se dichiariamo anche che possiamo fingere di essere un tipo diverso - Person:

class Man extends Human 
          implements Person ...

.. quindi possiamo usarlo ovunque, dove Personè richiesto. Dobbiamo solo soddisfare le persone "interface" (cioè implementare tutte le sue cose pubbliche) .

implementaltra classe? Questa è roba davvero interessante

La bella faccia di Javascript (uno dei vantaggi) è il supporto integrato della digitazione Duck ( vedi wiki ). Piccola citazione:

"Se cammina come un'anatra e fa schifo come un'anatra, allora deve essere un'anatra."

Quindi, in Javascript, se due oggetti diversi ... avessero un metodo simile (ad esempio render()) possono essere passati a una funzione che lo prevede:

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

Per non perderlo - possiamo fare lo stesso in Typescript - con più supporto per la digitazione. Ed è qui che

class implements class

ha il suo ruolo, dove ha senso

Nelle lingue OOP come C#... non c'è modo di farlo ...

Anche la documentazione dovrebbe aiutare qui:

Interfacce che estendono le classi

Quando un tipo di interfaccia estende un tipo di classe, eredita i membri della classe ma non le loro implementazioni. È come se l'interfaccia avesse dichiarato tutti i membri della classe senza fornire un'implementazione. Le interfacce ereditano anche i membri privati ​​e protetti di una classe base. Ciò significa che quando crei un'interfaccia che estende una classe con membri privati ​​o protetti, quel tipo di interfaccia può essere implementato solo da quella classe o da una sua sottoclasse.

Ciò è utile quando si dispone di una grande gerarchia di ereditarietà, ma si desidera specificare che il codice funziona solo con sottoclassi che hanno determinate proprietà. Le sottoclassi non devono essere correlate oltre a ereditare dalla classe base. Per esempio:

class Control {
    private state: any;
}

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

class Button extends Control implements SelectableControl {
    select() { }
}

class TextBox extends Control {
    select() { }
}

// Error: Property 'state' is missing in type 'Image'.
class Image implements SelectableControl {
    private state: any;
    select() { }
}

class Location {

}

Allora mentre

  • extends significa - ottiene tutto dal suo genitore
  • implementsin questo caso è quasi come implementare un'interfaccia. L'oggetto figlio può fingere di essere genitore ... ma non ottiene alcuna implementazione

quando dici " extends-ricevi tutto dal genitore", si applica ai membri privati? Per esempio class Person {private name: string} class man extends Person{gender: string;}ha manavere il nome della proprietà?
davejoem

Ci sono anche i privati. Appena inaccessibile da TS. Rendili protetti e puoi usarli. In caso di "attrezzi" ha senso solo la parte pubblica. Spero che aiuti un po '
Radim Köhler

Ottima risposta. Solo non sono sicuro dal tuo commento per "privato c'è ma non accessibile da TS". Vuoi dire che le proprietà private vengono copiate in quell'oggetto figlio appena creato? E nel caso degli attrezzi vengono copiati solo i beni pubblici?
kushalvm

Inoltre, ho capito un altro punto. Se questa è la definizione di si estende. Quindi per favore se si potrebbe spiegare questo stackoverflow.com/questions/60390454/...
kushalvm

98

Nel dattiloscritto (e in alcuni altri linguaggi OO) ci sono classi e interfacce.

Un'interfaccia non ha implementazione, è solo un "contratto" di quali membri / metodo ha questo tipo.
Per esempio:

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

Le istanze che implementano questa Pointinterfaccia devono avere due membri di tipo number: xand y, e un metodo distanceche riceve un'altra Pointistanza e restituisce un file number.
L'interfaccia non implementa nessuno di questi.

Le classi sono le implementazioni:

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));
    }
}

( codice in playground )

Nel tuo esempio tratti la tua Personclasse una volta come una classe quando la estendi e una volta come un'interfaccia quando la implementi.
Il tuo codice:

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

class Man implements Person {}

Ha un errore di compilazione che dice:

La classe "Man" implementa in modo errato l'interfaccia "Person".
La proprietà "name" non è presente nel tipo "Man".

E questo perché le interfacce mancano di implementazione.
Quindi, se sei implementuna classe, prendi solo il suo "contratto" senza l'implementazione, quindi dovrai farlo:

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

( codice in playground )

La conclusione è che nella maggior parte dei casi si desidera frequentare extendun'altra classe e non quella implement.


7
Questa risposta è più semplice da capire.
Akshay Raut

6

Ottima risposta da @ nitzan-tomer! Mi ha aiutato molto ... ho esteso un po 'la sua demo con:

IPoint interface;
Point implements IPoint;
Point3D extends Point;

E come si comportano nelle funzioni che si aspettano un IPointtipo.

Quindi quello che ho imparato finora e che ho usato come regola empirica: se stai usando classi e metodi che si aspettano tipi generici, usa le interfacce come i tipi previsti. E assicurati che il genitore o la classe base utilizzi quell'interfaccia. In questo modo puoi usare tutte le sottoclassi in quelle per quanto implementano l'interfaccia.

Qui la demo estesa


Questo non fornisce una risposta alla domanda. Per criticare o richiedere chiarimenti a un autore, lascia un commento sotto il suo post. - Dalla recensione
aronisstav

1
@aronisstav Ho solo pubblicato una demo estesa di quella che ho trovato una buona risposta che già mi ha aiutato. Ma forse qualcun altro potrebbe trovare utile il lavoro che ho fatto per estendere la demo. È tutto. I commenti non sono realmente pensati per inserire un blocco di codice, quindi è per questo che lo trovo più comprensibile in un messaggio di risposta. Allora qual è il problema con esso?
andzep

La tua risposta è stata (automaticamente?) Contrassegnata a causa della lunghezza e del contenuto, è apparsa nella mia coda di revisione e ho dato merito ai motivi presentati nella bandiera. Il suo contributo principale (spiegando che hai esteso la demo) sarebbe meglio come commento. Con il paragrafo aggiunto forse è davvero più utile.
aronisstav

@andzep il tuo esempio demo esteso è davvero utile.
namit

3
  1. L'interfaccia estende l'interfaccia con la forma
  2. L'interfaccia estende la classe con la forma
  3. La classe implementa l'interfaccia dovrebbe implementare tutti i campi forniti dall'interfaccia
  4. La classe implementa la classe con la forma
  5. La classe estende la classe con tutti i campi

extendsconcentrarsi sull'ereditarietà e implementsconcentrarsi sui vincoli sia che si tratti di interfacce che di classi.


0

Estende gli attrezzi VS

  • extends: La classe figlia (che è estesa) erediterà tutte le proprietà e i metodi della classe si estende
  • implements: La classe che utilizza la implementsparola chiave dovrà implementare tutte le proprietà e i metodi della classe che la utilizzaimplements

Per dirla in termini più semplici:

  • extends: Qui ottieni tutti questi metodi / proprietà dalla classe genitore, quindi non devi implementarlo da solo
  • implements: Ecco un contratto che la classe deve seguire. La classe deve implementare almeno i seguenti metodi / proprietà

Esempio:

class Person {
  name: string;
  age: number;

  walk(): void {
    console.log('Walking (person Class)')
  }

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
}
class child extends Person { }

// Man has to implements at least all the properties
// and methods of the Person class
class man implements Person {
  name: string;
  age: number

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  walk(): void {
    console.log('Walking (man class)')
  }

}

(new child('Mike', 12)).walk();
// logs: Walking(person Class)

(new man('Tom', 12)).walk();
// logs: Walking(man class)

Nell'esempio possiamo osservare che la classe figlia eredita tutto da Person mentre la classe man deve implementare tutto da Person stessa.

Se dovessimo rimuovere qualcosa dalla classe man, ad esempio il metodo walk, otterremmo il seguente errore in fase di compilazione :

La classe "uomo" implementa in modo errato la classe "Persona". Intendevi estendere "Persona" ed ereditare i suoi membri come sottoclasse? La proprietà "walk" non è presente nel tipo "man" ma è richiesta nel tipo "Person". (2720)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.