Home Testo Corso Swift Le Closure

Le Closure

614
0
Le-Closure

In questa lezione parleremo delle Closure.

Le Closure in Swift sono uno degli argomenti più ostici, non tanto nella scrittura del codice stesso ma più nel capire il loro funzionamento a livello teorico.

Sono presenti anche in altri linguaggi di programmazione, ad esempio, in Objective-C o Java dove prendono il nome di Block.

Per spiegarlo, utilizziamo un esempio fatto qunado abbiamo parlato delle funzioni, nello specifico quando abbiamo visto come passare una funzione come parametro di ingresso.

Se  non hai letto la lezione o non sai di cosa stiamo parlando ti invito a rivederla prima di continuare con questa lezione.

/Funzione Somma
func somma (numero01: Int, numero02: Int) -> Int{
    
    return numero01 + numero02
}

//Funzione Sottrazione
func sottrazione (numero01: Int, numero02: Int) -> Int{
    
    return numero01 - numero02
}

//Funzione Moltiplicazione
func moltiplicazione (numero01: Int, numero02: Int) -> Int{
    
    return numero01 * numero02
}

//Funzione Divisione
func divisione (numero01: Int, numero02: Int) -> Int{
    
    return numero01 / numero02
}

//Funzione Stampa
func stampa (funzione:(Int, Int) -> Int, v1: Int, v2: Int){
    
    print ("Risultato Operazione: \(funzione(v1,v2))")
}

stampa (funzione: somma, v1: 15, v2: 5)
stampa (funzione: sottrazione, v1: 15, v2: 5)
stampa (funzione: moltiplicazione, v1: 15, v2: 5)
stampa (funzione: divisione, v1: 15, v2: 5)

Nell’esempio se ti ricordi abbiamo 4 funzioni che eseguono le 4 operazioni e una funzione stampa che come parametro di ingresso ha un funzione e 2 parametri di tipo numerico.

Quindi passavano come parametro funzione stampa una funzione delle 4 operazioni e i numeri che volevamo calcolare.

Tramile le closure possiamo fare questa operazione con un unica funzione.

// Closure
 
 // chiamata di una closure
 
 richiamoNomeFunzione { () -> () in
 
 // comportamento della funzione passata come parametro
 }

Una Closure con il linguaggio Swift ci permette di definire il comportamento di un parametro, di tipo funzione, all’interno della chiamata di una qualsiasi funzione.

Quindi Invece di passare una funzione come parametro, si eseguono i seguenti passaggi:

  • Si scrive il nome della funzione da chiamare.
  • Si aprono le parentesi graffe.
  • Si scrive il tipo di dato della funzione passata al parametro.
  • Si fa seguire la parola chiave in.
  • Si scrive il comportamento della funzione che stai passando al parametro.
  • Si chiude la parentesi graffa
// Funzione che ha tra i parametri una funzione
func stampa(v1: Int, v2: Int, op: String, funzione:(Int, Int, String) -> Int){    
    print("Risultato operazione: (funzione(v1,v2,op))")   
}

// Richiamo la funzione e utilizzo una Closure
stampa2(v1: 5, v2: 5, op: "*") { (num01, num02 ,op2) -> Int in
    
    switch op2{
    
    case "+":
        return num01 + num02
        
    case "-":
        return num01 - num02
        
    case "*":
        return num01 * num02
        
    case "/":
        return num01 / num02
        
    default:
        return 0
    }  
}

Quindi tramite l’utilizzo della forma Closure ho eliminato le 4 funzioni operazioni e ho inserito il loro codici direttamente nella chiama della funzione stampa.

Nello specifico nella chiama della funzione stampa invece di inserire un riferimento a una delle funzione come del precedente esempio ho aperto le parentesi graffe, ho passato i tre parametri chiesti e il tipo in uscita poi dopo la parola chiave in ho inserito il codice da eseguire.

Questo sistema è un grande passo in avanti perché ci permette di circoscrivere il comportamento di una funzione tutto all’interno di un singolo blocco d’istruzioni (da questo ragionamento deriva infatti il termine Block o Closure).

Uno dei principali punti di forza di una Closure con il linguaggio Swift è sicuramente quello di poter racchiudere una funzione complessa in un solo blocco di istruzioni.

Anche se aumenta leggermente la complessità di scrittura, la cosa positiva è che si evita di dover scrivere diverse funzioni che potrebbero facilmente confondersi all’interno di progetti più complessi.

 In questo modo, possiamo cambiare senza grosse difficoltà il comportamento della funzione generale senza dover interagire sulle eventuali funzioni che comporrebbero il sistema.