Il existe deux types de fichier dans l'organisation de l'objective-C:
les fichiers d'interfaces (*.h) contenant la déclaration des variables d'instances et des méthodes
les fichiers d'implémentation (*.m) contenant l'implémentation des méthodes
On peut définir un des trois types de concept du langage :
la classe
le protocole
la catégorie
Voici un exemple de la déclaration d'une classe standard class1. On doit définir les deux fichiers: interface et implémentation
#import "superclass1.h"
@interface Class1:Superclass1 <liste de protocoles>
{
// variables d'instances
int i;
NSString *str;
}
// déclarations des méthodes
- (int) getInteger;
- (void) setName:
@end#import "class1.h"
@implementation Class1:Superclass1 <liste de protocoles>
//Implémentations des méthodes
- (int) getInteger
{
return i;
}
- setName: (NSString *) nom;
{
RELEASE(str);
str=nom;
}
@endDans ce cas on ne définit que le fichier d'interface. Comme en java, où l'on ne définirais que les interfaces des méthodes pour une interface.
@protocol Proto1 <liste de protocoles> //déclarations des méthodes - display; @end
La catégorie est un concept plutôt sympathique puisqu'il permet d'ajouter des méthodes à une classe déjà écrite sans toucher au code de cette classe ni même de la recompiler.
#import "class1.h" @interface Class1 (Categorie1) <liste de protocoles> //Attention pas de déclarations de variables //Déclarations des méthodes //cf. «Les classes» @end
#import "Categorie1.h" @implementation Class1 (Categorie1) //Implémentations des méthodes //cf. «Les classes» @end
Les objets comme dans les autres langages de ce type sont des structures contenant des variables d'instances auxquelles on associe des méthodes pour travailler sur ces variables. Soulignons que ce langages comme celui qui l'a inspiré (Smalltalk) est complètement objet : les classes sont des objets avec leurs méthodes et leurs variables.
Comme en C avec le type int, il existe un type par défaut en Objective-C. C'est le type id ; il peut représenter n'importe quel objet. En réalité c'est un pointeur sur la structure ou se trouve les variables d'instances de l'objet. Voici la définition d'un objet quelconque truc:
id truc;
On se sert du mot clé nil afin de définir l'objet vide. On peut trouver sa définition dans le fichier header <objc/objc.h>.
truc=nil;
Dans ce cas la variable truc vaut en mémoire 0 comme en C lorsqu'un pointeur est null.
Le compilateur en objective-C ne contrôle le typage des objets qu'en fonction de votre propre déclaration. Un objet peut être statiquement typé par sa propre classe ou par une des classes de sa hiérarchie.
NSString *maChaine; // statique id *maChaine; // dynamique
Dans ce cas le compilateur signalera à la compilation si un message semble inadapté à l'objet qui le reçoit. Si l'on type au contraire notre objet avec le type id nous n'aurons simplement plus d'alerte. De toute façon, il ne liera la méthode utilisée sur l'objet qu'au moment de l'exécution. Ce mécanisme de messagerie est le point fort de ce langage de programmation.
Pour appeler la méthode justDoIt sur un objet monObjet1 et recevoir la valeur de retour dans monObjet2 on écrira ;
monObjet2 = [monObjet1 justDoIt];
Ou si la méthode prends des arguments :
monObjet2 = [monObjet1 doItOnce:true]; // 1 argument i = [monObjet2 modulo:7:3] // 2 arguments sans nom avec valeur de retour [monObjet1 doItOnce:true Twice:false]; // 2 arguments nommés [monObjet2 add: 2, 6, 3]; // nombre d'argument multiples (cf. printf en C)
Lorsqu'on veut effectuer une action sur un objet, il suffit de lui envoyer un message. Cette objet effectuera la méthode appropriée sur sa structure de données. Plus qu'un précepte philosophique, cette définition des messages cache l'architecture du dynamisme dans l'objective-C. Comme nous l'avons vu précédemment, le compilateur ne lie pas les méthodes. C'est la fonction obj_msgSend() qui réalise cette tache à l'exécution. Le compilateur remplace tous les envoies de messages par l'appel de cette fonction.
[récepteur message{ : arg1 :arg2...}]; <=> obj_msgSend( récepteur, sélecteur, {,arg1,arg2...} );
Le sélecteur est un type particulier du langage, il est défini pour accélérer l'appel de la fonction obj_msgSend. Grace à quelques fonctions manipulant ces objets, on peut créer du code très dynamique en choisissant nous même le nom de la methode à invoquer au moment de l'éxécution (cf "le fonctionnement des messages").