Compatibile con Xcode 8

Extension e Protocol in Swift. Due strumenti senza limiti!

Con questa lezione, Extension e Protocol in Swift, e la successiva analizzerai una delle ultime nozioni utili e basilari per la comprensione di una qualsiasi classe e oggetto che ti si presenterà durante il prossimo corso e, più in generale, durante lo sviluppo di qualsiasi applicazione con il linguaggio Swift.

La lezione è divisa in due parti perché parlerò di due strumenti diametralmente opposti ma che hanno un impatto notevole sulla struttura di un progetto se utilizzati in simbiosi.

Uno tra questi, i Protocols, stanno cominciando a prendere piede tanto che si comincia a parlare di programmazione orientata ai protocolli come sostituto e complemento della programmazione orientata agli oggetti. Ma arriviamoci con calma.

Come di dicevo, ti parlerò di due strumenti:

  • Extension: Come la stessa parola suggerisce, ti permette di estendere le funzionalità di una classe già esistente. Capirai meglio il perché tra poco.
  • Protocol: Un protocollo, anche qui la parola non è a caso, è un documento da rispettare. Nella programmazione un protocollo sancisce quali metodi e attributi una classe dovrà obbligatoriamente implementare (In fondo alla pagine parlo dei Protocol).

Premetto che le potenzialità di questo argomenti si capiranno meglio quando avrai a che fare con le applicazioni, ma vederlo già ora ti permetterà di evitare l’effetto: “e questo che bip è?”

Quindi non perdiamoci in chiacchiere e diamo uno sguardo alle Extension e Protocols in Swift!

Extension

Estendere, per quanto riguarda la programmazione con il linguaggio Swift, significa aumentare le capacità di una classe creata da te o già esistenti.

Una extension in Swift è definita a partire dalla parola chiave extension seguita dal nome della classe cui si vuole estendere il comportamento, quindi:

Prima di passare a vedere l’implementazione del codice è necessario fare una considerazione di carattere empirico. 

La domanda che dovrebbe sorgerti spontanea è: perché dovrei utilizzare una extension quando posso modificare il corpo di una classe?

La domanda è più che lecita.

Ti ricordi quando ti ho parlato dell’importanza di scrivere il codice di una classe quanto più generico possibile?

Il succo di quella lezione era che, una delle best practice di un programmatore, è quella di scrivere classi che possono essere riutilizzate in altri progetti.

Ora immagina di aver creato una classe Utente e di volere un nuovo attributo, chiamato codiceFiscale, rappresentato da una String. In alcuni progetti vuoi che il codice fiscale venga calcolato a partire da delle proprietà già esistenti ed in altri progetti non vuoi che ci sia il codice fiscale.

Cosa fai? Modifichi ogni volta la struttura della classe o utilizzi una extension?

Vedrai nel corso di sviluppo applicazioni che molte delle classi che utilizzerai sono state già scritte da Apple o da altri sviluppatori per aumentare la velocità di scrittura di un’applicazione e diminuire la complessità di un progetto. Spesso capiterà che le classi che ti hanno fornito non soddisfano le esigenze del tuo progetto e, di conseguenza, vorrai poterle modificare.

Con le Extension in Swift riuscirai a farlo senza intaccare il codice originale che, molte volte, è bloccato in delle sorte contenitori che ti permettono solo di leggerne il contenuto.

Extension in Swift

Metodi e Computed Property

 

Ipotizziamo di possedere la seguente classe Utente. Questa classe va benissimo per la maggior parte delle applicazioni che ti ritroverai a creare. In alcune però, ti piacerebbe inserire anche il codice fiscale dell’utente.

Dato che la struttura è pressoché universale per tutti i progetti, non vuoi rovinarla e quindi decidi di adoperare una Extension:

Allora aggiungi una extension e all’interno vi aggiungi la proprietà read-only codiceFiscale che ti permetterà di generarlo partendo dalla combinazione delle proprietà nome ed età:

 

A questo punto il procedimento è abbastanza semplice. Devi far finta che l’extension abbia aggiunto la computed property o il metodo dentro la classe originale (nel nostro caso la classe Utente). Quindi, una volta creato un oggetto, potrai richiamarlo senza nessuna differenza:

Lo dico già da ora perché sarà una domanda frequente quando entrerai nel vivo dello sviluppo applicazioni. Dentro una Extension si possono aggiungere solamente:

  • Metodi cioè funzioni di qualsivoglia specie.
  • Computed Property cioè quelle con get o get-set.

Quindi, nelle extension non puoi inserire nuove proprietà (var e let). 

Un esempio tangibile

Le Extension, come ti dicevo, possono essere applicate sia alle classi già presenti che a quelle di sistema o contenuti in pacchetti non accessibili chiamati framework (vedrai durante lo sviluppo delle applicazioni).

Posso comunque farti vedere un esempio di Extension applicata ad una delle cose che già conosci ed utilizzi.

Esempio 0. Calcolare il numero di caratteri di una String.

Per esempio nelle String, che non sono classi ma strutture (nell’ultimo modulo ne parlo, comunque sono più o meno analoghe), per recuperare il numero di caratteri devi fare così:

Cioè devi entrare dentro la proprietà characters (che è un array di caratteri) per poi utilizzare il count che si utilizza sui classici array.

Potresti creare una extension sulla String che ti permetta di recuperare questo valore in maniera più veloce. Cioè potresti creare una computed property di tipo solo get che ti va a restituire il characters.count:

Cominci a notare le potenzialità di questo strumento?

Nella fattispecie quello che stai facendo è modificare il comportamento di una classe/struttura che non è presente nel tuo codice ma è conservata da qualche parte in maniera protetta. Quindi l’unico modo che hai per interagire con lei è utilizzando le Extension.

Voglio farti vedere un altro esempio sempre sulle String.

Esempio 1. Convertire una String in Int

Al momento se tu hai una stringa che ti rappresenta un numero, qual’è il sistema che utilizzi per convertila in un numero (per esempio Int)?

Un po’ macchinoso e ti obbliga ad eseguire due passaggi.

Potremmo creare una Extension che aggiunga una funzione che restituisca un Int direttamente dalla stringa:

Due cose da notare:

  1. Ho aggiunto la funzione toInt() alla precedente extension questo per farti capire che non è necessario creare un blocco extension ogni volta che vuoi apportare delle modifiche a qualcosa. Puoi mettere tutto dentro un’unica extension.
  2. Alla funzione toInt() ho messo come parametro d’uscita un Int Opzionale perché non tutte le stringhe rappresentano un numero, quindi il costruttore Int(<stringa>) può restituire nil (nel caso te lo stessi chiedendo, si dal costruttore init può uscire un nil ma non ne ho parlato durante il corso perché non è funzionale al nostro scopo).

protocolli-linguaggio-swift

Protocolli

Il protocollo, come la stessa definizione suggerisce, è qualcosa che ti impone di seguire delle specifiche ben precise. In programmazione, o meglio per il linguaggio Swift, il protocollo ha un’eccezione più larga ed applicabile su più fronti.

Il protocollo in Swift, è un tipo di dato astratto che definisce ciò che una classe qualsiasi è obbligata a contenere, senza imporre una implementazione precisa. 

Un protocollo ti dice cosa devi implementare ma non ti da indicazioni del come farlo. 

La mamma che ti urla di sistemare il letto ti sta imponendo un protocollo. Quando tua mamma entrerà nella stanza per vedere se effettivamente hai sistemato il letto, sicuramente troverà delle imperfezioni, ma sarai salvo perché lei non ti ha mai detto come farlo. L’esempio della mamma può essere esteso tranquillamente ad una ragazza/o o moglie/marito :D.

Un protocollo viene definito a partire dalla parola chiave protocol seguita dal nome del protocollo:

Una classe è forzata ad utilizzare un protocol definendone l’ereditarietà (alla stregua di quanto hai fatto con le sottoclassi). Quindi, ipotizzando una classe Figlio, che obbedisce agli ordini del protocollo imposto dalla mamma, quello che accadrebbe sarebbe qualcosa del genere:

Come puoi notare, se non scrivi niente all’interno della classe, Xcode, ti comunica che c’è un errore: “class X does not conform to protocol A, questo vuol dire che la classe Figlio non sta rispettando ciò che gli è stato imposto dal OrdiniMammaProtocol.

Per risolvere il problema basta implementare i metodi, dopo vedremo gli attributi, del protocol OrdiniMammaProtocol. Non importa come venga implementato, puoi fare anche la pipì sul letto, l’importante è che venga riportato all’interno della classe:

Aggiungere Attributi

Un protocol può forzare anche l’inserimento di variabili e costanti all’interno di una classe. La particolarità sta nel fatto che ti obbliga a definire se queste debbano essere delle normali proprietà get-set o delle proprietà solo get.

 

Da notare come viene fatto seguire, al tipo di dato, un blocco contenete esclusivamente o la parola chiave get, per indicare una read only property, o entrambi gli accessori get e set (read and write property).

In conclusione, anche in questo caso il protocol non impone una linea guida sul modo di implementazione delle proprietà:

Una proprietà del protocollo definita con {get set} non deve obbligatoriamente essere di tipo computed property, cioè con l’implementazione del get e set. Una normalissima variabile è già di tipo get-set dato che gli puoi assegnare un nuovo valore (set) e recuperarlo (get).

Perché utilizzarli?

Una solita domanda sorge spontanea quando si trattano argomenti dall’ambigua utilità, perché utilizzarli?

Se già l’extension ha suscitato un po’ di dubbi, Il concetto di protocollo del linguaggio Swift ne solleva molti altri ancora.

La domanda che mi sono posto io, quando ho studiato per la prima volta i protocolli (in Java prendono il nome di Interface) è stata la seguente:

Se il codice lo scrivo io, perché dovrei creare qualcosa in più che potrei anche evitare? Cioè! Hai ben visto che il protocol impone di inserire degli attributi o metodi ad una classe, ma se la classe la costruisci sempre tu, perché non creare già la classe con quelle specifiche?

Esattamente quello che continuo a chiedermi tutt’ora! No aspetta, Sto scherzando :D

Una delle cose che spero di averti trasmesso, più che il codice vero in se, è la capacità di pensare ad una soluzione invece che provare a risolvere il problema scrivendo codice a caso (cosa che definisce il 90% degli sviluppatori attuali).

Uno dei metodi che si ha per progettare una classe è quella di scriverne il blueprint. Un blueprint è il modello spoglio della classe, una fotografia sfocata di quello che sarà la classe.

Le interfacce o protocolli navigano ad un livello superiore rispetto ad una super classe. I protocolli sono astrazione a tutti gli effetti ed è proprio quest’astrazione che ti permette di focalizzarti più sulla struttura che sul codice in se.

In questo modo, tutto ciò che è astratto potrai descriverlo partendo da un protocollo più che da una classe super generica che poi non andrai mai ad utilizzare perché utilizzerai sempre una subclass di quella classe.

 

Quindi, in generale, un protocol può essere utilizzato per:

  1. Evitare di creare una superclasse che poi non verrà utilizzata.
  2. Forzare una o più classi ad utilizzare ed implementare dei metodi e attributi che ritieni necessari.
  3. Crea una struttura più solida per la rappresentazione delle gerarchie tra classi. Infatti puoi pensare anche di creare più protocols e implementarli in classi diverse:

In realtà ci sono altri motivo. Un altro motivo che si chiama: Pattern di programmazione Delegate e te ne parlerò quando arriverai al corso di sviluppo applicazioni iOS in Swift. Parlerò dei Delegate in una lezione del prossimo corso dato che è più funzionale vederlo in azione con un’applicazione.

Considerazioni

Imparare ad utilizzare le Extension e Protocol in Swift è più di una semplice routine o prassi, è la realizzazione di un percorso che si chiama “la via del buon sviluppatore”.

Più avanti andrai e più vedrai che le classi cominceranno ad occupare pagine e pagine intere.

Trovare un sistema elegante che ti permetta di snellire il codice, come può essere fatto con il protocolli o le extension del linguaggio Swift ti permetterà di risparmiare più tempo di quello che attualmente pensi.

Come ti dicevo, la vera potenza di questi due strumenti la comincerai a vedere nel prossimo corso (che puoi già cominciare). Comunque, ormai sei agli sgoccioli. Il Type Casting e la Gestione degli Errori ti daranno il quadro completo del linguaggio Swift.

Buona Programmazione!

Changelog

  • 7/11/2016 – Aggiunto il changelog. Modifiche al testo e assicurata compatibilità con Xcode 8 ed il linguaggio Swift 3.0.

Torna a: Corso gratuito linguaggio di programmazione Swift > Programmazione ad oggetti in Swift

Start typing and press Enter to search

type-casting-in-swift