swift

Le extensions permettono di aggiungere funzionalità a classi esistenti, strutture, enumerazioni e protocolli.

Attraverso un esempio sarà subito tutto più chiaro: creiamo delle funzionalità estese al tipo Double (che di fatto è una struttura). Dichiariamo una costante distanza di tipo Double e facciamo in modo che acquisica delle proprietà di conversione tra Km, m, cm ecc..

extension Double {

    var Km: Double { return self / 1000.0 }

    var m: Double { return self }

    var cm: Double { return self * 100.0 }

    var mm: Double { return self * 1000.0 }

}

let distanza: Double = 200.m

print(distanza.Km) //Stampa: 0.2

 

Con extension si crea una estensione del tipo Double aggiungendo delle proprietà calcolate (computed properties) le quali altro non sono che variabili in grado di restituire un valore calcolato sul valore assunto dalla stessa variabile (uso della parola chiave self). L'estensione Km viene dichiarata con la sintassi consueta per le variabili e viene definita come Double; il suo valore però è frutto del calcolo ottenuto dal valore della variabile stessa (self) diviso 1000.

Nell'esempio, la costante distanza acquisisce il valore 200 metri. Successivamente leggendo la proprietà distanza.Km ottengo lo stesso valore opportunamente ricalcolato (200m = 0.2Km).

Le extensions possono essere usate per creare metodi per aggiungere comportamenti o modificarne di esistenti. Si supponga di voler modificare i numeri interi in modo da aggiungere una proprietà che ripeta il numero di volte indicato una funzione arbitraria. E' decisamente un comportamento bizzarro ma evidenzia la potenza di extension. Quello che vogliamo ottenere è che 3.ripeti { print("Ciao") } stampi tre volte la stringa ciao.

extension Int {

    func ripeti(task: () -> Void) {

        for _ in 0..<self {

            task()

        }

    }

}

3.ripeti {

    print("Ciao")

}

//Ciao

//Ciao

//Ciao

 

Viene creata l'extension al tipo Int e viene definita la funzione ripeti. Questa funzione prende come parametro il tipo ()->Void che significa una funzione senza alcun parametro che non restituisce alcunché. In Swift quasi ogni cosa è un tipo, quindi oltre ai tipi tradizionalmente conosciuti in programmazione come int o char esistono tipi come quello sopra descritto che identificano un certo tipo di funzione (quella che non prende parametri e non restituisce valori). Per fare un esempio analogo il tipo (String)->Int è qualunque funzione che riceve come parametro una stringa e restituisce un numero intero. Definire il parametro task di questo tipo vuol dire che alla funzione ripeti posso passare una qualunque funzione purché il tipo della funzione che viene passata sia uguale a quello indicato.

La funzione ripeti esegue un ciclo for con il contatore che va da 0 al valore indicato dal numero intero (self = 3) il ciclo for rilancia per self volte la funzione passata nel parametro task. Il carattere underscore nel ciclo for viene utilizzato per rimpiazzare una variabile che non venendo utilizzata verrebbe definita inutilmente.

L'estensione può anche modificare il valore stesso inizialmente attribuito alla variabile. Facciamo l'esempio di una variabile intera che viene ridefinita da una funzione creata all'interno della extension.

extension Int {

    mutating func elevatoAlCubo() {

        self = self * self * self

    }

}

var mioInt = 3

mioInt.elevatoAlCubo()

print(mioInt)

// Stampa 27

 

Se la funzione definita nella extension modifica o muta il valore inizialmente attribuito alla variabile la funzione deve essere definita mutating.