Gran parte della programmazione object-oriented consiste nella scrittura di codice per nuovi oggetti, definendo quindi nuove classi. In Objective-C le classi vengono definite in due parti:
- Un’interfaccia dove vengono dichiarati i metodi, le variabili di istanza della classe e il nome della sua superclasse
- Un’implementazione che è la reale definizione della classe (contiene il codice vero e proprio per implementare i suoi metodi)
File sorgenti
Anche se il compilatore in realtà non lo richiede, l’interfaccia e l’implementazione sono solitamente separati in due file differenti. Il file di interfaccia deve essere reso disponibile a chiunque utilizzi la classe.
Un singolo file puo’ dichiarare o implementare più di una classe. Ciononostante, è consuetudine avere file di interfaccia e di implementazione separati per ogni classe. Lasciare le interfacce delle classi separate riflette meglio la loro natura indipendente.
Il nome di questi file solitamente coincide con il nome della classe. Il nome del file di implementazione ha estensione .m e indica che esso contiene il codice sorgente scritto in Objective-C. Al file di interfaccia puo’ essere assegnata qualsiasi altra estensione. Dato che questi vengono inclusi in altri file, il loro nome solitamente ha estensione .h, tipida dei file di intestazione. Per esempio, la classe “Rectangle” della lezione precedente dovrebbe essere dichiarata in Rectangle.h e definita in Rectangle.m.
Separare l’interfaccia di un oggetto dalla sua implementazione si adatta perfettamente alla progettazione di programmi object-oriented. Un oggetto può essere visto dall’esterno come un’entità simile a una “scatola nera” che vive di vita propria.
Class Interface
La dichiarazione di un’interfaccia di una classe inizia con la direttiva per il compilatore “@interface” e termina con la direttiva “@end”. (Tutte le direttive per il compilatore in Objective-C iniziano con il carattere “@”)
@interface ClassName : ItsSuperclass
{
instance variable declarations
}
method declarations
@end
La prima linea della dichiarazione presenta il nome della nuova classe e un collegamento alla sua superclasse. La superclasse definisce la posizione della nuova classe nella struttura gerarchica legata all’ereditarietà spiegata nella lezione precedente. Se i duepunti e il nome della superclasse sono omessi, la nuova classe è dichiarata come una classe radice (root class), allo stesso livello della classe NSObject.
Guardando la prima parte della dichiarazione, potete vedere come tra le parentesi graffe vengono racchiuse le dichiarazioni delle variabili di istanza, ovvero le strutture dei dati che sono parte di ogni istanza della classe. Di seguito un esempio di variabili di istanza che potrebbero essere dichiarate nella classe “Rectangle”:
float width;
float height;
BOOL filled;
NSColor *fillColor;
I metodi per la classe sono dichiarati successivamente, dopo la chiusura della parentesi graffa che termina la dichiarazione delle variabili e prima della chiusura della dichiarazione della classe (prima di “@end”).
I nomi dei metodi che possono essere usati dagli oggetti di classe, metodi di classe, sono preceduti dal segno più “+”:
+ alloc;
I metodi che possono invece usare le istanze di una classe, metodi di istanza, sono preceduti dal segno meno “-“:
- (void)display;
Anche se non è una pratica comune, è possibile definire un metodo di classe e un metodo di istanza con lo stesso nome. Un metodo puo’ inoltre avere lo stesso nome di una variabile di istanza. Questo è più comune, specialmente se il metodo restituisce il valore nella variabile. Per esempio, Circle ha un metodo raggio che potrebbe corrispondere alla variabile di istanza raggio.
I tipi di ritorno dei metodi sono dichiarati usanto la sintassi per il casting da un tipo ad un altro usata nello standard C:
- (float)radius;
I tipi di dato per gli argomenti sono dichiarati allo stesso modo:
- (void)setRadius:(float)aRadius;
Se il tipo restituisto dal metodo o il tipo degli argomenti non è esplicitamente dichiarato, viene assunto il tipo di default ID. Come ad esempio il metodo alloc, illustrato poco fa.
Quando c’è più di un argomento, questi sono dichiarati dentro il nome del metodo dopo i duepunti. L’argomento spezza il nome nella dichiarazione, come in un messaggio. Per esempio:
- (void)setWidth:(float)width height:(float)height;
I metodi che accettano un numero variabile di argomenti vengono dichiarati utilizzando una virgola e i punti di puntini di sospensione:
- makeGroup:group, ...;
Importare l’interfaccia
Il file di interfaccia deve essere incluso in ogni modulo che dipende da essa, incluso ogni modulo che crea un’istanza della classe, invia messaggi per invocare un metodo dichiarato per la classe o fa riferimento a una variabile di istanza dichiarata al suo interno. Per inportare l’interfaccia si usa la direttiva “#import”;
#import "Rectangle.h"
Questa direttiva è identica a “#include” tranne che per il fatto che assicura che lo stesso file non venga mai incluso più di una volta.
Dato che la classe eredita metodi e variabili da una superclasse, nella definizione dell’interfaccia occorre importare l’interfaccia della sua superclasse:
#import "ItsSuperclass.h"
@interface ClassName : ItsSuperclass
{
instance variable declarations
}
method declarations
@end
Quindi tutti i file di interfaccia includono, indirettamente, i file d’interfaccia delle loro superclassi. Quando un modulo di codice importa un’iternfaccia di una classe, esso eredita tutte le interfacce delle superclassi nella struttura gerarchica su cui si basa la classe stessa.
Riferimenti ad altre classi
Come abbiamo appena detto un file di interfaccia dichiara una classe e importando la sua superclasse, implicitamente contiene la dichiarazione di tutte le classi ereditate, da NSObject procedendo verso il basso fino alla sua superclasse. Se ci si riferisce ad una classe che non è in questa gerarchia è importante dichiaralra tramite la direttiva @class:
@class Rectangle, Circle;
Questa direttiva informa semplicemente il compilatore che “Rectangle” e “Circle” sono nomi di classi. Non importa i file delle loro interfacce.
Implementazione
La definizione della classe è strutturata in modo molto simile alla sua dichiarazione. Inizia con la direttiva “@implementation” e termina con la direttiva “@end”
@implementation ClassName : ItsSuperclass
{
instance variable declarations
}
method definitions
@end
Tuttavia, ogni file di implementazione deve importare la propria interfaccia. Per esempio, Rectangle.m importerà Rectangle.h. Nell’implementazione non è quindi necessario ripetere quanto contenuto nell’interfaccia, si può tranquillamente omettere:
- Il nome della superclasse
- Le dichiarazioni delle variabili di istanza
#import "ClassName.h"
@implementation ClassName
method definitions
@end
I metodi per una classe sono definiti, come le funzioni in C, tra una coppia di parentesi graffe.
Prima delle parentesi sono invece dichiarate allo stesso modo di come sono state dichiarate nel file di interfaccia, ma senza il punto e virgola finale. Ad esempio:
+ (id)alloc
{
...
}
- (BOOL)isFilled
{
...
}
- (void)setFilled:(BOOL)flag
{
...
}
(Tradotto dalla documentazione ufficiale Apple)












4 Responses to “L#007 – Objective-C (Parte II) Definizione di una classe”
15 Dicembre 2009
iphone dev ssh -www.sens2.noblogs.org « Sensperiodit’s Blog[…] http://www.devapp.it/wordpress/l007-%E2%80%93-objective-c-parte-ii.html#more-660 […]
8 Maggio 2010
NicolaMolto utile, ho chiarito molti dubbi che avevo leggendo i tutorial pratici…
13 Luglio 2010
Alessandrocomplimenti. chiari, precisi ed utili.
continuate con le vostre guide!
13 Luglio 2011
MaveDevSempre utili le vostre guide, grazie mille, continuate cosi 🙂