74 TS – Estendere una classe

Se per esempio usiamo lo stemmo nome per 2 classi, nello stesso percorso, anche se in 2 files diversi, ci viene segnalato che il nome deve essere univoco.

Vediamo una classe AnimalBase e una Birds estensione della prima, tramite la keyword extends

class AnimalBase {
    name : string
    constructor(name: string){
        this.name = name;
    }

    getName(){
        return 'il mio nome è' + this.name;
    }
}

class Birds extends AnimalBase {

}

Già così posso utilizzare la classe Birds richiamando i metodi presenti nella classe genitore

let dove = new Birds('Colomba');
console.log(colomba.getName());

Mi viene restituito il mio nome è colomba.

Aggiungiamo una sua property per il luogo dove vive alla classe Birds e un metodo che la restituisca

class Birds extends AnimalBase {
    place : string
    getPlace() : string {
        return this.place;
    }
}

se lancio dove.getPlace() mi restituisce undefined, perché place non stato settato da nessuna parte, aggiungiamo un metodo per settare la proprietà place

class Birds extends AnimalBase {
    place: string;

    getPlace(): string {
        return this.place;
    }
    setPlace(place: string): void {
        this.place = place;
    }
}

adesso possiamo ottenere il risultato di place che restituisce  “al mare”

let dove = new Birds('Dove');
dove.setPlace('al mare');
console.log(dove.setPlace());

Se per esempio oltre al nome Dove (colomba) volessimo passare anche il luogo direttamente nei parametri dell’oggetto, dovremmo inserire un costruttore anche nella classe estesa Birds. 

class Birds extends AnimalBase {
    place: string;
    
    constructor() {

    }

    getPlace(): string {
        return this.place;
    }

    setPlace(place: string): void {
        this.place = place;
    }
}

Estendiamo il costruttore padre

Già in questo modo  il nostro IDE ci segnalerebbe errore, perché la classe figlia non può stanziare un nuovo costruttore, se questo è già presente nella classe genitore, ma deve richiamarlo tramite l’attributo super

constructor(name: string, place: string) {
    super(name);
}

Quindi abbiamo invocato il costruttore della classe madre ora possiamo aggiungere la proprietà place, ma attenzione, generebbe errore se dichiarassimo la proprietà prima della super classe, e quindi prima di super. Più in generale in presenza di una super classe, le proprietà aggiuntive DEVONO essere dichiarate dopo il super.

constructor(name: string, place: string) {
    super(name);
    this.place = place;
}

adesso nell’oggetto dove ritroviamo l’errore che manca un parametro, quindi o lo aggiungiamo

let dove = new Birds('Dove', 'mare');

oppure possiamo metterlo di default nel costruttore

constructor(name: string, place: string = 'mare') {
    super(name);
    this.place = place;
}

Override dei metodi

Aggiungiamo per. esempio un metodo move() nella classe genitore AnimalBase che riceve una proprietà distance

move(distnce: number){
    console.log('Mi sono spostato di ' + distnce + ' metri')
}

quindi se nell’oggetto dove chiamo move passando per esempio 50

dove.move(50);

Ottengo:

Mi sono spostato di 50 metri 
il mio nome è colomba
mare

Se invece volessimo sovrascrivere il metodo move, perchè per esempio voglio scrivere che vola essendo un uccello, nella classe birds scrivo l’override, ma prima, inserendo lo stesso metodo, il programma mi compila in automatico così

move(distance: number) {
    super.move(distance);
}

Questo come abbiamo visto è il richiamo al metodo genitore, tale e quale, ma noi vogliamo sovrascriverlo

move(distance: number) {
    console.log('Ho volato di ' + distance + ' metri');
}