Interfacce Funzionali Generiche in Java
- Le interfacce funzionali in Java possono essere generiche, permettendo di definire metodi che operano su tipi di dati specificati al momento della creazione dell'istanza.
- Le espressioni lambda possono essere utilizzate con interfacce funzionali generiche, consentendo di scrivere codice più flessibile e riutilizzabile.
- Le interfacce funzionali generiche permettono di definire metodi che accettano e restituiscono tipi di dati specifici, migliorando la leggibilità e la manutenibilità del codice.
Interfacce Funzionali Generiche
Un'espressione lambda, di per sé, non può specificare parametri di tipo. Pertanto, un'espressione lambda non può essere generica.
Naturalmente, a causa dell'inferenza di tipo, tutte le espressioni lambda mostrano alcune qualità simili ai tipi generici o generics.
Tuttavia, l'interfaccia funzionale associata a un'espressione lambda può essere generica. In questo caso, il tipo target dell'espressione lambda è determinato, in parte, dall'argomento di tipo o dagli argomenti specificati quando viene dichiarato un riferimento all'interfaccia funzionale.
Per comprendere il valore delle interfacce funzionali generiche, consideriamo questo. I due esempi nelle lezioni precedenti utilizzavano due interfacce funzionali diverse, una chiamata FunzioneNumerica
e l'altra chiamata FunzioneStringa
:
interface FunzioneNumerica {
int funzione(int n);
}
interface FunzioneStringa {
String funzione(String str);
}
Tuttavia, entrambe definivano un metodo chiamato funzione()
che prendeva un parametro e restituiva un risultato. Nel primo caso, il tipo del parametro e il tipo di ritorno era int
. Nel secondo caso, il parametro e il tipo di ritorno era String
. Pertanto, l'unica differenza tra i due metodi era il tipo di dati che richiedevano. Invece di avere due interfacce funzionali i cui metodi differiscono solo nei loro tipi di dati, è possibile dichiarare un'interfaccia generica che possa essere utilizzata per gestire entrambe le circostanze.
Il seguente programma mostra questo approccio:
// Utilizzo di un'interfaccia funzionale generica con espressioni lambda.
// Un'interfaccia funzionale generica.
interface QualcheFunzione<T> {
T funzione(T t);
}
// Una classe che dimostra l'uso di QualcheFunzione.
class DemoInterfacciaFunzionaleGenerica {
public static void main(String[] args)
{
// Utilizza una versione basata su String di QualcheFunzione.
QualcheFunzione<String> inverti = (str) -> {
String risultato = "";
int i;
for(i = str.length()-1; i >= 0; i--)
risultato += str.charAt(i);
return risultato;
};
// Ora, usa l'interfaccia funzionale generica
// per invertire le stringhe.
System.out.println("Lambda invertita è " +
inverti.funzione("Lambda"));
System.out.println("Espressione invertita è " +
inverti.funzione("Espressione"));
// Ora, utilizza una versione basata su Integer di QualcheFunzione.
QualcheFunzione<Integer> fattoriale = (n) -> {
int risultato = 1;
for(int i=1; i <= n; i++)
risultato = i * risultato;
return risultato;
};
// Ora, usa l'interfaccia funzionale generica
// per calcolare il fattoriale di due numeri.
System.out.println("Il fattoriale di 3 è " +
fattoriale.funzione(3));
System.out.println("Il fattoriale di 5 è " +
fattoriale.funzione(5));
}
}
L'output è mostrato qui:
Lambda invertita è adbmaL
Espressione invertita è enoisserpsE
Il fattoriale di 3 è 6
Il fattoriale di 5 è 120
Nel programma, l'interfaccia funzionale generica QualcheFunzione
è dichiarata come mostrato qui:
interface QualcheFunzione<T> {
T funzione(T t);
}
Qui, T
specifica sia il tipo di ritorno che il tipo di parametro di funzione()
. Questo significa che è compatibile con qualsiasi espressione lambda che prende un parametro e restituisce un valore dello stesso tipo.
L'interfaccia QualcheFunzione
è utilizzata per fornire un riferimento a due diversi tipi di lambda. Il primo utilizza il tipo String
. Il secondo utilizza il tipo Integer
. Pertanto, la stessa interfaccia funzionale può essere utilizzata per riferirsi al lambda inverti
e al lambda fattoriale
. Solo l'argomento di tipo passato a QualcheFunzione
differisce.