lunedì 3 maggio 2010

Guida Objective-C in Italiano - Selettori - Parte 11


Oggi parleremo dei Selettori del linguaggio Objective-C; vi ricordo che questa è l'undicesima parte della Guida in Italiano alla programmazione in Objective-C, e che nella barra laterale del sito potrete trovare tutti i links agli articoli di questa guida.

Questo post è una traduzione in italiano della Guida all'Objective C, presente sul sito developer.apple.com a questo link. L'Objective C è il linguaggio di programmazione per creare applicazioni per iPhone. Questo articolo può interessare a tutti gli sviluppatori che vogliono imparare le basi di questo linguaggio che è il fondamento per programmare nuove applicazioni per Mac Os X, iPhone ed iPad.


Selettori

In Objective-C, la parola selettore ha due significati. Può essere usata per riferirsi semplicemente al nome di un metodo quando è usato in un messaggio ad un oggetto nel codice sorgente. Si può anche riferire all'identificatore univoco che rimpiazza il nome quando il codice sorgente è compilato. i selettori compilati sono di tipo SEL. Tutti i metodi con lo stesso nome hanno lo stesso selettore. Puoi usare un selettore per invocare un metodo su un oggetto - questo fornisce le basi per l'implementazione del pattern di progettazione target-azione in Cocoa.

Metodi e Selettori

Per efficienza, i nomi full ASCII non sono usati come selettori di metodo nel codice compilato. Invece, il compilatore scrive ogni nome di metodo in una tabella e poi accoppia il nome con un identificatore univoco che rappresenta il metodo a runtime. Il sistema di runtime si assicura che ogni identificatore sia univoco: non ci sono due selettori che sono uguali, e tutti i metodi con lo stesso nome hanno lo stesso selettore.

SEL e @selector

I selettori compilati sono assegnati a un tipo speciale, SEL, per distinguerli dagli altri dati. I selettori validi non sono mai 0. Devi permettere al sistema di assegnare identificatori SEL ai metodi; è futile assegnarli arbitrariamente.

La direttiva @selector() ti permette di riferirti ai selettori compilati, piuttosto che al completo nome del metodo. Qui, il selettore per setWidth:height: è assegnato alla variabile setWidthHeight:
SEL setWidthHeight;

setWidthHeight = @selector(setWidth:height:);

è più efficiente assegnare valori a variabili SEL a tempo di compilazione con la direttiva @selector(). Comunque, in alcuni casi, potresti aver bisogno di convertire una stringa di caratteri ad un selettore a runtime. Puoi farlo con la funzione NSSelectorFromString:
setWidthHeight = NSSelectorFromString(aBuffer);
Le conversioni sono possibili anche nella direzione opposta. La funzione NSStringFromSelector restituisce un nome di metodo per un selettore:
NSString *method;

method = NSStringFromSelector(setWidthHeight);

Metodi e Selettori

Selettori compilati identificano nomi di metodi, non implementazioni di metodi. Il metodo display per una classe, ad esempio, ha lo stesso selettore di un metodo display definito nelle altre classi. Questo è essenziale per il polimorfismo e il collegamento dinamico; permette di inviare lo stesso messaggio a riceventi appartenenti a classi diverse. Se ci fosse un selettore per ogni implementazione di metodo, un messaggio non sarebbe differente da una chiamata di funzione.

Un metodo di classe e un metodo di istanza con lo stesso nome sono assegnati allo stesso selettore. Comunque, a causa dei loro domini separati, non c'è confusione tra i due. Una classe potrebbe definire un metodo di classe display in aggiunta al metodo d'istanza display.

Valori di Ritorno e Tipi di Argomenti dei Metodi

La routine di messaggistica ha accesso alle implementazioni dei metodi solo attraverso i selettori, quindi li tratta allo stesso modo tutti i metodi con lo stesso selettore. Scopre i tipi restituiti di un metodo, e i tipi di dati dei suoi argomenti, dal selettore. Quindi, eccetto per messaggi inviati a riceventi tipati staticamente, il collegamento dinamico richiede che tutte le implementazioni dei metodi con lo stesso nome debbano avere lo stesso valore di ritorno e tipi di argomenti. (riceventi staticamente tipati sono un eccezione a questa regola, dato che il compilatore può imparare l'implementazione del metodo dal tipo della classe).

Sebbene i metodi di classe con lo stesso nome e i metodi di istanze siano rappresentati dallo stesso selettore, possono avere argomenti diversi e tipi di ritorno diversi.

Variare il Messaggio a Runtime

I metodi performSelector:, performSelector:withObject:, e performSelector:withObject:withObject:, definiti nel protocollo NSObject, prendono gli identificatori SEL come loro argomenti iniziali. Tutti e tre i metodi mappano direttamente nella funzione di messaggistica. Per esempio:
[friend performSelector:@selector(gossipAbout:)

withObject:aNeighbor];

è equivalente a:
[friend gossipAbout:aNeighbor];
Questi metodi rendono possibile variare un messaggio a runtime, come è possibile variare l'oggetto che riceve il messaggio. I nomi di variabili possono essere usati in entrambe le metà di un'espressione di un messaggio:
id helper = getTheReceiver();

SEL request = getTheSelector();

[helper performSelector:request];

In questo esempio, il ricevente (helper) è scelto a runtime ( dalla funzione fittizia getTheReceiver), e il metodo che il ricevente è chiesto di eseguire (request) è anch'esso determinato a runtime (dalla funzione ugualmente fittizia getTheSelector).

Nota: performSelector: e i suoi metodi compagni restituiscono un id. Se il metodo che è eseguito restituisce un tipo diverso, dovrebbe essere fatto un cast al tipo appropriato. (comunque, fare il cast non funziona per tutti i tipi; il metodo dovrebbe restituire un puntatore o un tipo compatibile con un puntatore).

Il Design Pattern Target-Azione

Nel suo trattamento di controlli di interfacce utente, l'Application Kit fa buon uso dell'abilità di variare sia ricevente che messaggio.

Oggetti NSControl sono graficamente dispositivi che possono essere usati per dare istruzioni ad un'applicazione. La maggior parte somigliano a dispositivi di controllo del mondo reale come bottoni, interruttori, campi di testo, menu ecc... Nel software questi dispositivi si trovano tra applicazione e utente. Essi interpretano gli eventi che vengono dai dispositivi hardware come la tastiera ed il mouse e li traducono in istruzioni specifiche per l'applicazione. Per esempio, un pulsante etichettato "Find" tradurrebbe un click del mouse in un'istruzione per l'applicazione per iniziare a cercare qualcosa.

L'Application Kit definisce un modello per creare dispositivi di controllo e di suo, definisce pochi dispositivi immediatamente disponibili. Ad esempio, la classe NSButtonCell definisce un oggetto che puoi assegnare ad un'istanza di NSMatrix ed inizializzare con una taglia, un'etichetta, un'immagine, un carattere, e una tastiera alternativa. Quando l'utente clicca sul pulsante (o usa la tastiera alternativa), l'oggetto NSButtonCell invia un messaggio che istruisce l'applicazione a fare qualcosa. Per fare questo, un oggetto NSButtonCell deve essere inizializzato non solo con un'immagine, dimensione ed etichetta ma con direzioni su che messaggio inviare e a chi inviarlo. Di conseguenza un'istanza di NSButtonCell può essere inizializzata per un messaggio d'azione, il selettore del metodo che dovrebbe usare nel messaggio che invia, ed il target, l'oggetto che dovrebbe ricevere il messaggio.
[myButtonCell setAction:@selector(reapTheWind:)];

[myButtonCell setTarget:anObject];

Il pulsante cella invia il messaggio usando il metodo performSelector:withObject: di NSObject. Tutti i messaggi d'azione prendono un singolo argomento, l'id del dispositivo di controllo che invia il messaggio.

Se Objective-C non permettesse ai messaggi di essere variati, tutti gli oggetti NSButtonCell dovrebbero inviare lo stesso messaggio; il nome del metodo dovrebbe essere congelato nel codice sorgente di NSButtonCell. Invece di implementare semplicemente un meccanismo per traslare le azioni dell'utente in messaggi d'azione, i pulsanti celle e altri controlli dovrebbero vincolare il contenuto del messaggio. Questo renderebbe difficile per qualunque oggetto rispondere a più di un button cell. Ci dovrebbe anche essere un unico target per un pulsante, o l'oggetto target dovrebbe scoprire da quale bottone viene il messaggio e agire di conseguenza.

Ogni volta che riorganizzi l'interfaccia utente, dovresti anche re-implementare il metodo che risponde al messaggio azione. Questa sarebbe una complicazione non necessaria che l'Objective-C evita felicemente.

Evitare Errori nei Messaggi

Se un oggetto riceve un messaggio per eseguire un metodo che non è nel suo repertorio, risulterà un errore. è la stessa sorta di errore di chiamare una funzione non esistente. Ma poiché i messaggi occorrono a runtime, l'errore spesso non è evidente finché il programma non viene eseguito.

è relativamente semplice evitare questi errori quando il selettore del messaggio è costante e la classe dell'oggetto ricevente è conosciuta. Come scrivi i tuoi programmi, puoi accertarti che il ricevente sia in grado di rispondere. Se il ricevente è tipato staticamente, il compilatore esegue questo test per te.

Comunque, se il selettore dl messaggio o la classe del ricevente varia, potrebbe essere necessario post-porre questo test fino a runtime. Il metodo respondsToSelector:, definito nella classe NSObject, determina se un ricevente può rispondere ad un messaggio. Prende il selettore di metodo come un argomento e restituisce se il ricevente ha accesso a metodi che combaciano con il selettore:
if ( [anObject respondsToSelector:@selector(setOrigin::)] )

[anObject setOrigin:0.0 :0.0];

else

fprintf(stderr, "%s can’t be placed\n",

[NSStringFromClass([anObject class]) UTF8String]);

Il test respondsToSelector: è specialmente importante quando si inviano messaggi ad oggetti di cui non hai il controllo al tempo di compilazione. Ad esempio, se scrivi codice che invia un messaggio ad un oggetto rappresentato da una variabile che altri possono impostare, dovresti accertarti che il ricevente implementi un metodo che risponda al messaggio.

Nota: Un oggetto si può anche sistemare per avere i messaggi che riceve, inoltrati ad altri oggetti se esso non può rispondere direttamente ai messaggi da solo. In tal caso, appare che l'oggetto può gestire il messaggio, anche se l'oggetto risponde al messaggio indirettamente assegnandolo ad un altro oggetto.

Fine Parte 11

Finisce qui l'undicesimo articolo di questa Guida dedicato ai Selettori del linguaggio di programmazione Objective-C. Il prossimo post di questa guida, parlerà della Gestione delle Eccezioni.

Segnalatemi eventuali errori, o commentate l'articolo se l'avete trovato utile, anche per incentivarmi a continuare a pubblicare le mie traduzioni. Iscrivetevi ai feed del blog per essere sempre aggiornati automaticamente ogni volta che sono disponibili nuovi contenuti.
Nella barra laterale del blog potete trovare l'elenco di tutti gli articoli di questa guida.


Nessun commento:

Posta un commento

Related Posts with Thumbnails