
Oggi torniamo a parlare di programmazione ad oggetti ed impareremo un’aspetto importante di questo paradigma di programmazione che, una volta compreso, può farci risparmiare righe di codice e renderà i nostri programmi migliori, perchè meno codice equivale ad una minore probabilità di bug nascosti.
Parleremo del costrutto protocol.
Probabilmente chi ha già sviluppato qualche programma in questo linguaggio l’ha già incontrato, magari in quei fastidiosi “warning” che ci avvisano di non aver implementato tutti i metodi del protocollo tal dei tali, ma cos’è in realtà il costrutto protocol e a cosa serve?

Un po’ di storia
Il protocol (o interface in java ) nasce per sopperire alla mancanza dell’ereditarietà multipla, risolvendo il problema del diamante tagliando, di fatto, la gerarchia delle classi.
Non ci avete capito nulla? è normale, non spaventatevi, tornate a leggere questa frase dopo aver letto tutto l’articolo, se allora vi sarà più chiara vorrà dire che ho fatto bene il mio lavoro.
I protocol rientrano in una aspetto della OOP chiamto polimorfismo, ovvero la caratteristica che hanno gli oggetti trattati dalla OOP di poter “avere più forme” o meglio di poter essere trattati non come un unico tipo, ma come il suo tipo specifico e tutti i tipi che lo precedono nella gerarchia delle classi, a differenza dei tipi primitivi che invece hanno per definizione un solo tipo.
Ad esempio un eggetto di tipo UILabel possiamo vederlo sia come UILabel, ma è anche una UIView, un UIResponder e un NSObject e possiamo utilizzare su di lui tutti i metodi previsti da questi oggetti. Una variabile primitiva di tipo int, invece, è solo un “int” e posso usarlo solo dove viene richiesto un int.
Nota per gli smaliziati: lo so che il C non è fortemente tipizzato quindi posso usare un “int” anche dove viene richiesto un “char”, ma non facciamo troppo i fiscali!
Questa struttra gerarchica è molto versatile, ma alle volte il mondo reale non è così ordinato come noi programmatori vorremo, quindi potrebbe nascere la necessità di ereditare da due classi differenti. Supponiamo che, dopo aver creato la classe “automobile” e la classe “barca”, vengano fuori delle auto anfibie come queste:

Se volessimo creare una classe per questo mezzo dovremmo esporre dei metodi specifici per l’automobile (frena) e dei metodi specifici per le barche (getta l’àncora) e probabilmente saremmo tentati di creare una classe che eredita sia da “automobile” che da “barca” per evitare di riscrivere tutti i metodi e tutte le proprietà di questi due mezzi.
Si presenta a questo punto un problema, noto appunto con il nome di “problema del diamante”. Supponiamo che le due classi “automobile” e “barca” abbiano entrambe il metodo “accelera”, magari perchè entrambe ereditano dalla classe astratta “veicolo” dove è specificato questo metodo, ma abbiamo due implementazioni diverse: una restituisce la velocità in kilometri e l’altra in nodi.
Se la nostra vettura anfibia eredita da entrambe le classi, e non effettua l’override del metodo “accelera” quando verrà invocato questo metodo quale codice verrà eseguito? Quello della classe “auto” o della classe “barca”?
Questo problema di chiama “del diamante” perchè una sua schematizzazione potrebbe ricordare un diamante (ma non provate a regalarlo alla vostra donna!).

Per risolvere questo problema alcuni linguaggi come il java ed il nostro caro obj-c non permettono di implementare l’ereditarietà multipla, eliminando il problema alla radice.
Purtroppo però i casi come la macchina anfibia nella realtà sono più comuni di quanto si pensi e, soprattutto se abbiamo sbagliato a creare la nostra gerarchia delle classi, viene proprio la voglia di fare copia/incolla di codice con tutti i problemi che conosciamo.
Per venirci incontro è stato creato il costrutto “interface” in java e “protocol” in obj-c che, anche se non risolve appieno il problema, almeno ci offre una mezza soluzione.
Protocol in pratica
Un “protocollo” è in pratica un unico file .h (senza il .m) dove vengono elencati i metodi che lo costituiscono, lo possiamo pensare come una sorta di “contratto”.
#import
@protocol NOME_PROTOCOLLO
- (void)primoMetodo;
- (void)secondoMetodo;
....
@end
Una classe può implementare uno o più protocolli, così facendo si impegna a fornire una implementazione ai metodi dei protocolli che ha implementato.
Questo sembrerebbe non aver risolto il nostro problema, perchè potremmo trovarci costretti a riscrivere due volte la stessa implementazione di un metodo di un protocollo in due classi separate che lo implementano, ma in compenso ci offre la possibilià di definire delle relazioni tra classi che non stanno sullo stesso ramo dell’albero delle gerarchie, per questo si dice che i protocol “tagliano l’albero delle gerarchie”.
In questo caso il “problema del diamante” non si può presentare perché nei protocolli non ci sono metodi implementati, ma solo le loro “signatures”
Protocol come tipo di dato
C’è un secondo aspetto che rende “protocol” un costrutto molto versatile ed è il seguente.
Supponiate di aver scritto il miglior algoritmo di ordinamento basato su confronti, un algoritmo fantastico che per ordinare n interi ci metta meno di nlogn tempo e lo vogliate vendere. Che tipi di dati ordinerebbe la vostra funzione? interi? stringhe? automobili?
Ovviamente se riusciste a fare una funzione generica che ordina qualsiasi tipo di dato sareste sicuri di venderne milioni di copie..ma come fare?
Se ci pensate bene l’unica cosa che vi interessa è che gli oggetti da ordinare espongano un metodo come “(int)compareTo:(id)obj” quindi voi potreste dire al vostro cliente “se il tuo oggetto ha questo metodo allora puoi usare la mia funzione”.
Per ottenere questo comodissimo risultato bisogna proprio sfruttare il costrutto procol!
In java il costrutto “interface” definisce un tipo di dato,quindi se avete creato un interface di nome “comparable” nell’algoritmo potete lavorare direttamente con oggetti di tipo comparable. Purtroppo in obj-c la cosa non è così comoda, il “protocol” non definisce un tipo di dato, quindi il massimo che possiamo fare è lavorare con oggetti di tipo generico e specificare al compilatore che questi oggetti “preferiremmo” che implementassero il protocollo “comparable”.
In questo modo:
UIView < NOME_PROTOCOLLO > *target;
Purtroppo il compilatore si può rendere conto solo di assegnazioni di tipo statico, quindi evidenzierà solo di errori in fase di compilazione. Per essere certi che gli oggetti su cui lavoriamo implementano davvero il protocollo “comparable” dobbiamo utilizzare il seguente codice:
if ([target conformsToProtocol:@protocol(NOME_PROTOCOLLO)] == YES ) {
//do something.
}
Implementare un protocollo
Per aiutare quindi il compilatore a segnalare anomalie nel codice è sempre buona norma specificare quali protocolli abbiamo intenzione di implementare nelle nostre classi. La sinstassi per far questo è la seguente
//nel file .h della dichiarazione della classe
@interface NOME_CLASSE : NOME_SUPERCLASSE < NOME_PROTOCOLLO > {
UIColor *baseColor;
}
A questo punto dovrebbe essere chiaro cosa significa
< UITableViewDelegate , UITableViewDataSource >
in testa ai nostri controller delle tabelle…
non si tratta altro che di due protocolli, e con questo codice la classe si impegna a fornire una implementazione ai metodi del protocollo.
Se le implementazioni sono parziali il compilatore segnalerà l’errore con un warning.
Alla prossima!

8 Responses to “L#014 – Un contratto tra la gli oggetti: il protocol”
18 Gennaio 2011
Tweets that mention Un contratto tra la gli oggetti: il protocol [Objective-C] | devAPP -- Topsy.com[…] This post was mentioned on Twitter by devAPP and Vanni Giannozzi. Vanni Giannozzi said: L#014 – Un contratto tra la gli oggetti: il protocol: Oggi torniamo a parlare di programmazione ad oggetti ed im… http://bit.ly/h0SPjV […]
18 Gennaio 2011
BrunoWow, questo è pesante…. 🙂
In realtà avevo già studiato la questione con Java, e mi è abbastanza chiara, ma ancora con obj-C devo sbatterci un po’ la testa…!
Domanda di servizio : che programma hai usato per creare il diagramma di flusso delle classi (Veicolo, Automobile, ecc…)?
In cambio ti segnalo alcuni refusi, in ordine di apparizione :
“warnig”
anfibibie
multipa
impementassero
18 Gennaio 2011
Ignaziocgrazie per il commento e per le segnalazioni (vergogna tremenda vergogna).
Il programma è il mitico google docs 🙂 niente licenza, niente installazione, cosa vuoi di più dalla vita?
18 Gennaio 2011
Brunomacché vergogna, gli errorini di battitura capitano a tutti.
Google Docs? Che stupido, non l’avevo riconosciuto…!
Avrei dovuto intuire dal colore! Grazie!
26 Gennaio 2011
marcoscusate la domanda fuori luogo ma come fate a caricare in una Tableview differenti detailView a seconda della cella che tocco?..vi prego aiutatemi perchè non trovo niente che mi aiuti
26 Gennaio 2011
NeoCiao, dai un’occhiata al forum:
http://www.devapp.it/wordpress/forum/showthread.php?531-Collegamenti-celle-table-view-con-viste-in-dettaglio
26 Gennaio 2011
marcoscusa la mia ignoranza ma il “detail” cosa dovrebbe essere nel mio codice?
1 Marzo 2011
Notifiche in stile growl per le nostre applicazioni iPhone e iPad | devAPP[…] mio precedente articolo parla proprio del costrutto @protocol leggetelo se avete difficoltà e non capite di cosa stiamo […]