Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Overloading delle funzioni

Come implementare definizioni diverse di una stessa funzione, sfruttare l'unione di tipi per dichiarare e gestire i tipi dei parametri.
Come implementare definizioni diverse di una stessa funzione, sfruttare l'unione di tipi per dichiarare e gestire i tipi dei parametri.
Link copiato negli appunti

Molti linguaggi tipizzati prevedono la possibilità di avere definizioni multiple di una stessa funzione o metodo, come nel seguente esempio di codice C#:

public int somma(int x, int y) { ... }
public int[] somma(int[] x, int[] y) { ... }
public int somma(int[] x) { ... }

In questo esempio, la funzione somma() viene definita per lavorare su due argomenti di tipo intero, su due argomenti di tipo array di interi e su un argomento di tipo array di interi. Per ciascuna definizione avremo comportamenti leggermente diversi: nel primo caso otterremo la somma di due numeri, nel secondo caso avremo un array i cui elementi sono la somma dei corrispondenti elementi degli array originari e nel terzo caso ci verrà restituita la somma degli elementi dell'array. Naturalmente, il comportamento di ciascuna definizione di funzione dipende dalla specifica implementazione, ma nel nostro caso supponiamo che sia questo il comportamento voluto.

Notiamo come la stessa definizione abbia in input un numero di argomenti e tipi di dato diversi. Lo stesso vale per l'output: le diverse definizioni restituiscono valori interi o un array di interi. Questa caratteristica supportata dalla maggior parte dei linguaggi di programmazione orientata agli oggetti è chiamata overloading.

In JavaScript non è difficile implementare una funzione che abbia lo stesso effetto delle definizioni multiple. Dal momento che il linguaggio è dotato di una tipizzazione dinamica delle variabili, ciascuna variabile non è vincolata a contenere valori di un determinato tipo, ma può contenere valori di tipi diversi che possono cambiare durante l'esecuzione dell'applicazione. Questa caratteristica, combinata con il fatto che gli argomenti di una funzione possono essere opzionali, ci consente di implementare facilmente il supporto di un numero variabile di argomenti con diverse combinazioni di tipo.

Ma in un linguaggio tipizzato come TypeScript, come possiamo implementare l'overloading delle funzioni?

Il numero variabile degli argomenti è già garantito dal linguaggio che consente di definire argomenti opzionali o con valori predefiniti. Per supportare il fatto di poter accettare argomenti di tipo diverso possiamo far ricorso all'unione di tipi. Si tratta di una sintassi che consente di indicare che per un argomento sono accettabili valori di un tipo oppure di un altro, come mostrato dal seguente esempio:

function somma(x:number | number[], y:number | number[]):number|number[];

Con questa dichiarazione diciamo che la funzione somma() accetta due argomenti x e y. Ciascun argomento può essere un numero oppure un array di numeri e la funzione restituisce un numero oppure un array di numeri. Alla dichiarazione di funzione deve seguire poi l'effettiva implementazione, come ad esempio quella seguente:

function somma(x, y) { 
    var risultato; 
    if (typeof x === "number" && typeof y === "number") {
        risultato = x + y;
    } 
    if (typeof x === "object" && typeof y === "object") {
        var i = 0;
        risultato = [];
        for (i = 0; i < x.length; i++) {
            risultato.push(x[i] + y[i]);
        }
    } 
    if (typeof x === "object" && typeof y === "undefined") {
        var i = 0;
        risultato = 0;
        for (i = 0; i < x.length; i++) {
            risultato = risultato + x[i];
        }
    }
    return risultato;
}

Sebbene questa implementazione segua in qualche modo le specifiche date nella dichiarazione, essa non supporta combinazioni di parametri che la dichiarazione implicitamente accetta. Ad esempio, in base alla dichiarazione della funzione somma() noi potremmo invocarla passando un valore numerico e un array di numeri, ma questa combinazione non è prevista dall'implementazione.

Per essere più precisi nella dichiarazione occorre specificare esattamente le combinazioni di tipi di dato previsti in ingresso e i corrispondenti tipi di dato in uscita. Per fare ciò ricorriamo ad una definizione multipla della funzione somma():

function somma(x:number, y:number):number;
function somma(x:number[], y:number[]):number[];
function somma(x:number[]):number;

In questo modo abbiamo stabilito che soltanto le combinazioni indicate sono accettabili e in corrispondenza di ciascuna combinazione di input otterremo il rispettivo tipo di output.


Ti consigliamo anche