Quando nasce
Chiunque voglia entrare nel mondo della programmazione targato “Apple” inevitabilmente si imbatte nell’ objective-C. Questo linguaggio di programmazione, ovviamente orientato agli oggetti come descrive il nome, prende sempre più piede grazie alla diffusione degli apparati Apple venduti. L’objective-C venne partorito dalla Stepstone nel 1981 e fu progettato per essere un estenzione del C con degli accorgimenti in più rispetto al C++ (dinamic binding, run-time identification e persistenza).
Nel 1988 la NeXT, società fondata da Steve Jobs, il cofondatore della Apple, acquisisce la licenza dell’objective-C cedutagli dalla Stepstone. Più tardi nel 1996 la Apple incorpora la NeXT e con essa tutti i diritti associati all’objective-C ed è con tale linguaggio che la Apple tuttora implementa il suo sistema operativo non solo degli iMac ma anche di tutti i suoi dispositivi.
Il compilatore
Il compilatore della Apple è basato sullo standard dei compilatori GNU, infatti dato che la sintassi dell’ objective-c è un superset del GNU C/C++ questi compilatori lavorano anche con programmi scritti in C/C++. Il compilatore riconosce i file objective-c dall’estenzione .m mentre i file scritti in C dall’estenzione .c e i file scritti in C++ dall’estenzione .mm. Entriamo ora nel dettaglio della sintassi.
Creare una classe
Definizione della classe
In objective-c per interfaccia si intende una classe, quindi una classe va definita e implementata. Come nello standard C si ha un file di definizione della classe (.h) e un file di implementazione della classe (.m). Per quando riguarda i compilatori Apple essi vengono forniti di un framework standard che ci da le funzionalità base, il Foundation framework . Per definire una classe procediamo nel seguente modo:
1 #import <Foundation/NSObject.h>
2
3 @interface Fraction: NSObject {
4 int numerator;
5 int denominator;
6 }
7
8 -(void) print;
9 -(void) setNumerator: (int) n;
10 -(void) setDenominator: (int) d;
11 -(int) numerator;
12 -(int) denominator;
13 @end
- Nella riga 1 importiamo la clase NSObject (NextStep Object) che sarà la classe base di tutti gli oggetti, anche se non è strettamente necessario.
- Dalla riga 3 alla riga 6 viene definita la classe. Quindi per definire la classe si utilizza la seguente sintassi “@interface <nome classe> : <superclasse> { … }”. Nel nostro caso la classe Fraction estende NSObject.
- Nelle righe 4 e 5 vengono dichiarate le variabili di istanza, senza modificatore public o private in questo caso sono protected.
- Al di fuori delle parentesi graffe dalla riga 8 alla 12 evngono definiti i metodi della classe.
- I metodi sono definiti con la seguente sintassi “scope (tipo di dato restituito) nome metodo: (tipo parametro 1) nome paramentro 1″. Nel nostro caso ad esempio nella riga 9 viene definito il metodo setNumerator che restituisce un void (quindi nulla) ed ha un parametro intero indentificato con la n. Il simbolo “-” ad inizio riga indica lo scope del metodo, quindi il metodo setNumerator è un metodo di istanza, se volessimo creare un metodo di classe, cioè statico, basterebbe sostituire il simbolo “-” con “+”.
- Nella riga 13 viene indicata la fine della definizione della classe.
Implementazione della classe
L’implementazione della classe sopra definita viene scritta in un file con estensione .m, come segue:
1 #import "Fraction.h"
2 #import <stdio.h>
3
4 @implementation Fraction
5 -(void) print {
6 printf( "%i/%i", numerator, denominator );
7 }
8
9 -(void) setNumerator: (int) n {
10 numerator = n;
11 }
12
13 -(void) setDenominator: (int) d {
14 denominator = d;
15 }
16
17 -(int) denominator {
18 return denominator;
19 }
20
21 -(int) numerator {
22 return numerator;
23 }
24 @end
- La prima e la seconda riga ci permettono di includere due header files, uno che ci permette di importare delle librerie standard (stdio.h) e l’altro file è la definizione della classe che andiamo ad implementare (Fraction.h).
- Nella riga 4 si comincia con l’implementazione della classe vera e propria, la sintassi è quindi: @implementation <nome classe> … @end
- All’interno della classe troviamo l’implementazione di tutti i metodi definiti nel file .h, quindi alla riga 5 troviamo l’implementazione del metodo print, che si spiega da solo…
- Alla riga 9 c’è la definizione di un metodo con un parametro in ingresso come si nota dall’esempio la signature del metodo è praticamente identica alla definizione con in più il corpo del metodo tra parentesi graffe.
Utilizziamo la classe
La classe appena definita per poter funzionare bisogna essere richiamata in qualche punto del programma. L’objective-C come tutti i buoni linguaggi di programmazione ha il proprio metodo main che si definisce praticamente come nello standard C/C++, per cui:
1 #import <stdio.h>
2 #import "Fraction.h"
3
4 int main( int argc, const char *argv[] ) {
5 // create a new instance
6 Fraction *frac = [[Fraction alloc] init];
7
8 // set the values
9 [frac setNumerator: 1];
10 [frac setDenominator: 3];
11
12 // print it
13 printf( "The fraction is: " );
14 [frac print];
15 printf( "\n" );
16
17 // free memory
18 [frac release];
19
20 return 0;
21 }
- Come di consueto nei programmi c per poter utilizzare una classe bisogna importala, quindi nelle prime due righe del nostro codice di esempio importiamo la libreria standard, che ci serve per poter utilizzare il metodo printf, e la definizione di classe che abbiamo scritto noi.
- Alla riga 4 si parte con l’implementazione del metodo main che è scritto in maniera standard come il C classico.
- Il codice scritto alla riga 6 non fa altro che istanziare un nuovo oggetto della classe Fraction. In objective-C tutti gli oggetti sono trattati come puntatori per cui la dichiarazione dell’oggetto avviene cosi: Fraction *fract; Per quanto riguarda l’inizializzazione avviene in due fasi, prima viene creata l’istanza con il metodo alloc (metodo statico della classe Fraction ereditato da NSObject) e all’istanza di ritorno viene applicato il metodo init che è un costruttore standard sempre ereditato dalla classe NSObject.
- Alle righe 9 e 10 vengono richiamati i metodi da noi implementati quindi setNumerator e getNumerator.
- Alla riga 18 viene liberata la memoria occupata dall’oggetto dato che nn ci serve più e permettera al garbage collector di riutilizzare la memoria prima occupata.
Dall’esempio abbiamo capito alcune cose importati, come ad esempio che per richiamare un metodo in objective-c non esistono i costrutti tipici del C++ come nomeOggetto.nomeMetodo oppure nomeOggetto->nomeMetodo ma si richiama un metodo con la seguente sintassi [nomeOggetto nomeMetodo]. In oltre per liberare memoria bisogna indicare direttamente al compilatore quando si possono dereferenziare gli oggetti, diversamente da quello che succede in java, dove l’interprete si accorge automaticamente quando un oggetto non è più referenziato e lo segna per il garbage collector.
Grazie mille, dopo mille tutorial e guide che non ci capivo una mazza, questo è il primo tutorial dove riesco finalmente a capire e fare qualcosa….
Grazie e ciao
Di nulla figurati… è solo una piccola introduzione…
I casini arrivano dopo!!!!!
Grazie per l’intro, anche per me è la prima che trovo che mi fa capire qualcosa!
Avendo buone basi di C e Java, sapresti consigliarmi qualche libro per approfondire l’Objective C?