Aller au menu - Aller au contenu

[Plan du site] Vous êtes ici --- > Le Site du Zéro > Les tutoriels > Non-Officiels > Systèmes d'exploitation > MacOS > La programmation Mac > Le langage de programmation : Objective-C > Les messages > Lecture du tutoriel

Les messages

Vous vous apprêtez à lire un tutoriel rédigé par un membre de ce site. Malgré tout le soin que ce membre a pu apporter au tutoriel, nous ne pouvons pas garantir que les informations contenues sur cette page sont exactes à 100%. Merci de garder cela en tête lorsque vous lirez cette page ;o)
Avatar
Auteur : psychoh13
Note : 17 / 20 (2 votes)
Visualisations : 3 214

Plus d'informations Plus d'informations
Voilà : maintenant, on peut passer à la programmation objet... Vous allez enfin comprendre ce que signifie cette fameuse première instruction sur le NSAutoreleasePool. Vous allez découvrir les messages et comment on les écrit, ainsi que la déclaration des objets et leur utilisation. Vous allez aussi découvrir un exemple d'objet avec la classe NSString pour illustrer l'envoi de message.
Sommaire du chapitre :
Icône du chapitre
Chapitre précédent Sommaire

La syntaxe

Voilà comment on écrit un message :

Code : Autre
1
[receveur message];

il ne faut pas oublier le point-virgule ";" à la fin de chaque instruction comme en C, les messages ne dérogent pas à la règle.
Expliquons ce petit texte. Le receveur du message, c'est tout simplement un objet, on met tout simplement le nom de la variable.

En Objective-C, tous les objets doivent être déclarés comme des pointeurs sur objet ! Il ne faut jamais oublié la petite étoile devant le nom de votre variable. En revanche, lors de l'appel du message on ne met pas cette petite étoile.

Et le "message" est tout simplement le nom de la méthode et ses arguments.

Dans le code créé par Xcode, nous avons déjà 3 exemples d'envoi de message. Pour commencer, vous voyez qu'on déclare une NSAutoreleasePool nommée *pool, vous remarquez la présence de la petite étoile que je vous interdis d'oublier pour les objets ! :D
Regardons les crochets les plus à l'intérieur : [NSAutoreleasePool alloc]
Ici, le receveur du message est NSAutoreleasePool... Je vous avais parlé des objet-classes, eh bien en voici un, c'est l'objet-classe de la classe NSAutoreleasepool, on lui envoie le message alloc qui lui demande de créer une instance, c'est-à-dire un objet, de NSAutoreleasePool en lui attribuant de l'espace mémoire.

Les méthodes, comme les fonctions, peuvent renvoyer quelque chose. En l'occurrence la méthode alloc renvoie un id. id est un pointeur sur objet tout ce qu'il y a de plus banal. Contrairement aux autres types, celui-là ne nécessite pas d'étoile, vous pouvez écrire : id monObjet;, cela créera un pointeur sur un objet quelconque sans spécification, vous pourrez y mettre n'importe quel type d'objet après.

Ici donc notre méthode alloc renvoie un id, en l'occurrence il s'agit d'une NSAutoreleasePool ; le problème, c'est que cet objet est inutilisable après l'appel d'une méthode alloc, il nécessite une initialisation. Comme alloc renvoie un objet, et qu'on peut mettre n'importe quel objet comme receveur d'un message, il est possible de faire l'allocation et l'initialisation en un seul bloc.
C'est ce que fait la première instruction : on envoie le message init à l'objet retourné par la méthode alloc. init est la méthode d'initialisation par défaut de tous les objets, elle ne prend aucun argument, tout comme alloc et renvoie id, tout comme alloc. À la fin de l'instruction, on a créé un objet NSAutoreleasePool alloué et initialisé, et on a mis l'adresse de cet objet dans notre variable *pool. pool devient donc un objet NSAutoreleasePool.

Si on voulait faire cette instruction en plusieurs instructions différentes, cela ressemblerait à ça :

Code : Autre
1
2
3
NSAutoreleasePool *pool;
pool = [NSAutoreleasePool alloc];
[pool init];

Mais pour des raisons de simplification et de réduction du code, on réduit ces 3 instructions en une seule. C'est comme ça que vous créerez un objet généralement, mais il y a d'autres façons.

La Classe NSString

De même qu'en C++ avec la classe string, Objective-C possède lui aussi sa propre classe pour gérer les chaînes de caractères. Il s'agit de NSString. Je vous en ai déjà plus ou moins parlé : en fait, quand vous écrivez quelque chose comme @"ma chaine", vous déclarez un objet de type NSString. Une chaîne de caractères NSString statique pour être précis. Les NSString sont les seuls objets de tout Objective-C dont vous n'aurez pas à gérer la mémoire, alors profitez-en :D .

Je vous parle de cette classe pour vous présenter les méthodes incluant des arguments. Et aussi pour vous montrer d'autres façons de créer des objets :magicien: .
Donc, créons une petite NSString à partir d'un format, c'est-à-dire une chaîne de caractères à laquelle on ajoute des variables, des %d et autres... :

Code : Autre
1
2
3
4
int unNombre = 5; // Nombre qu'on affichera dans la chaîne
NSString *stringe; // On déclare notre NSString
stringe = [NSString stringWithFormat:@"\nMon nombre : %d\n",unNombre];
NSLog(stringe); // On affiche la NSString


Vous devez insérer ce code entre la déclaration de la NSAutoreleasePool et l'instruction [pool release];.

Regardons le message qu'on envoie à NSString : vous remarquez l'apparition des deux points ":" dans le nom de la méthode. Ces deux points font bel et bien partie du nom de la méthode. Le nom, c'est bien stringWithFormat: et non pas stringWithFormat, la virgule se trouvant à la suite de notre chaîne n'en fait en revanche pas partie. Il s'agit simplement là d'un format qui se construit de la même façon qu'en C : la première partie représente la chaîne à écrire, et les virgules séparent les variables à introduire dans la chaîne.

Donc, voilà : pour la création d'objet, vous avez donc deux techniques :
  • la technique en deux instructions : elle nécessite l'utilisation de la méthode suivie d'une méthode d'initialisation, les méthodes d'initialisation commencent généralement par init... ;
  • la technique en un seul message : ce sont des méthodes de classe, donc des messages à envoyer aux objet classes ; le nom de ces méthodes commencent généralement par le type construit par la méthode, en l'occurrence il s'agit d'une string.

À présent, parons des arguments. Les arguments à passer dans un message sont toujours précédés de deux points ":". Si vous avez une méthode qui prend 4 arguments, le nom de cette méthode ressemblera à ça : maMethode::::. Ce n'est pas très explicite, n'est-ce pas ? Voilà une grosse différence avec le C et les autres langages de ce genre... Comme les deux points font partie du nom de la méthode, il est possible d'expliciter chaque argument en écrivant ce qu'il signifie juste avant les deux points, par exemple : afficherLaDate:dansLaFenetre:aLaCouleur:etLaTaille: lorsque vous appellerez une méthode comme celle-ci, vous réécrirez tout en mettant juste après les deux points vos arguments :

Code : Autre
1
[ecran afficherLaDate:maDate dansLaFenetre:maFenetre aLaCouleur: rouge etLaTaille: taille];

Xcode permet notamment d'écrire les noms des méthodes sur plusieurs lignes en superposant les deux points ":" pour améliorer la lisibilité.

Il ne faut pas oublier de mettre un espace entre l'argument et la suite du nom de la méthode, sinon ça ne voudra plus rien dire :D . Vous pouvez aussi mettre un espace après les deux points, mais ce n'est pas obligatoire.


Est-ce qu'il est possible de mettre un message en argument ?

Bien sûr, à condition que ce message retourne quelque chose, car comme en C, un message peut retourner void, mais il peut aussi retourner les types primitifs comme int ou float ; là, il faut faire attention à passer les bon types de variables.

En Objective-C, comme en C, il est possible d'avoir des méthodes avec un nombre d'arguments variable. La méthode stringWithFormat: en est une. Seuls les arguments se trouvant en fin de message sont en nombres variables. Vous ne verrez pas de méthode de ce genre uneString:maChaine, maVar couleur:uneCouleur.

Les utilisations communes

Allez, revoyons comment on utilise généralement les messages.


Les messages ne retournant rien



C'est ceux qu'on voit généralement, on les met seuls sur une instruction. J'entends par là que les crochets de messages comme eux doivent être les plus à l'extérieur. On utilise ce genre de messages pour demander à un objet de s'afficher sur un écran par exemple, ou alors de modifier une de ses variables d'instance. Les modificateurs sont généralement des méthodes qui ne retournent rien, c'est-à-dire void, exemples :

Code : C
1
2
[text setColor:uneCouleur];
[fichier open];



Les messages retournant "id"



Ces messages sont assez pratiques, ils retournent généralement le receveur du message. C'est un peu bizarre, mais ça permet de faire en une seule instruction des envois de messages en cascades sur le même objet. L'objet visé étant l'objet se trouvant au niveau le plus bas dans les accolades, exemple :

Code : Autre
1
[[[[receveur message1] message2] message3] message4];


Attention ! Cela peut nuire à la clarté du code. :D


Ce genre d'instruction est pratique dans le cas des constructions d'objets.

Les "constructeurs"



J'ai mis "constructeurs" entre guillemets parce qu'ils ne sont pas comme en C++. En Objective-C, on utilise une méthode pour créer un espace mémoire et une méthode pour initialiser cet espace, l'allocation s'appelle sur l'objet classe. Alors qu'en C++, un constructeur s'appelle sur l'objet construit et ne retourne rien. Chez nous, il retourne quelque chose : l'objet construit. Cet objet est de type id, c'est-à-dire que vous pouvez le stocker aussi bien dans une variable de type id que dans une variable du type créé. Exemple :

Code : Autre
1
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];



Les messages retournant un autre objet qu'eux-mêmes



Ces messages-là retournent généralement un type précis, il s'agit généralement d'accesseurs. Ils permettent de récupérer la valeur d'une variable d'instance (on va voir ce que c'est lors de la définition des classes) qu'ils implémentent. On peut là aussi mettre ces messages en receveurs d'autres messages, mais le message ne sera pas reçu par le receveur du premier message. Exemple :

Code : Autre
1
[uneFenetre contentView];

Cette méthode, on la verra en interface graphique ; grosso-modo, elle permet de récupérer le contenu de la fenêtre uneFenetre.


Les messages retournant autre chose que des objets



Il s'agit là aussi généralement d'accesseurs, ou de résultats de calculs, ils retournent des variables primitives comme en C, par exemple des structures, des int, des float, etc. Tout ce qu'une fonction C normale est capable de retourner.

Si c'est pareil, à quoi sert la couche C de l'Objective-C ?

C'est sûr qu'on pourrait se créer une classe qu'on n'instancierait jamais et qui contiendrait des méthodes faisant des calculs simples, genre l'addition de deux structures. Mais on ne fait pas ça. Quand on envoie un message, le runtime doit découvrir le type du receveur, vérifier s'il peut exécuter la méthode et ensuite la lui faire exécuter. Ce sont des opérations très lourdes pour une addition de structures. Donc, on préférera utiliser les méthodes lorsque l'objet et ses variables d'instance sont directement impliquées, et on utilisera les fonctions pour les codes n'impliquant pas les objets. Cela fait partie du dynamisme du C de pouvoir aussi utiliser des fonctions ne passant pas par le runtime et permettant ainsi d'accroître la vitesse d'exécution.

Donc les messages retournant des variables autres que des objets sont généralement des accesseurs, ou alors des calculs impliquant les variables d'instance de l'objet receveur. Exemple :

Code : Autre
1
NSPoint resultat = [transformation transformPoint:unPoint];

Cette méthode, envoyée à un objet de la classe NSAffineTransform, retourne les coordonnées du point unPoint après application de la transformation transformation... On verra encore ça en interface graphique :D .


Un message comme argument



Comme je l'ai dit plusieurs fois, il est possible de mettre un message comme receveur d'un autre message. À condition que le message receveur retourne un objet ! Mais il est aussi possible de mettre un message en argument, à condition que celui-ci retourne aussi une valeur, mais là, ça peut être aussi bien un type primitif qu'un objet, il faut tout de même s'assurer que le type retourné corresponde au type de l'argument. Exemple :

Code : Autre
1
[uneImage drawInRect:[unBouton bounds]];

Encore de la programmation graphique. Ici, le message bounds envoyé à un bouton retourne un NSRect qui est une structure représentant la position et la taille du bouton. Ça tombe bien parce que la méthode drawInRect: prend en paramètre un NSRect.


Lorsque le type retourné est un type de base



Dans l'exemple ci-dessus, le type retourné par la méthode bounds est un NSRect qui est une simple structure contenant deux structures définies comme telles :

Code : Autre
1
2
3
4
5
6
7
8
9
10
11
12
13
14
typedef struct _NSPoint {
        float x;
        float y;
} NSPoint;

typedef struct _NSSize {
        float width;
        float height
} NSSize;

typdedef struct _NSRect {
        NSPoint origin;
        NSSize size;
} NSRect;

Il est possible d'accéder aux valeurs contenues dans la structure directement à partir du message sans passer par une variable intermédiaire de cette façon :

Code : C
1
[unBouton bounds].size.height;


Il est aussi possible d'utiliser les opérateurs "+", "-", etc. pour les types non-construits comme les int, float, double...

Donc vous voyez que les messages sont finalement très flexibles et permettent pas mal de tours de passe-passe réduisant la charge de travail.

Q.C.M.

Quel symbole permet d'identifier les arguments d'un message ?
Si mon message est le suivant :

Code : Autre
1
[unObjet stringWithCode: 5 andFormat:@"Ma chaine formatee : %@",uneStringe];

Le nom de la méthode sera :
Il est possible de mettre un message en argument d'un autre message si celui-ci :
Il est possible de mettre comme receveur d'un message :
Quel symbole permet d'identifier les arguments d'un message ?
Si mon message est le suivant :

Code : Autre
1
[unObjet stringWithCode: 5 andFormat:@"Ma chaine formatee : %@",uneStringe];

Le nom de la méthode sera :
Il est possible de mettre un message en argument d'un autre message si celui-ci :
Il est possible de mettre comme receveur d'un message :

Statistiques de réponses au QCM


Ce qui conclut le chapitre sur les messages. Vous touchez ici du doigt la programmation dynamique à la Objective-C... Nous allons à présent passer aux choses sérieuses en programmant nous-mêmes nos propres classes en les faisant interagir avec les classes fournies par Apple.
Chapitre précédent Sommaire
Retour en haut Retour en haut


Créé : le 01/04/2007 à 00:41:59
Modifié : le 13/10/2008 à 17:14:27
Avancement : 100%
Licence : Copie non autorisée

L'orthographe, la grammaire et la présentation de ce tutoriel ont été vérifiées par les zCorrecteurs.

Changer de design | En savoir plus | Plan du site | Politique d'accessibilité | Règles | RSS tutoriels | RSS news
Édité par Simple IT SARL : Nous contacter | Notre blog | Revue de presse | Publicité

Y'a plus rien à lire, faut remonter maintenant !

Hébergement web - Correction de tutoriels - Créer un site
Vous souhaitez apparaître ici ? Contactez-nous.

Nombre de connectés 438 Zéros connectés | Requêtes SQL 8 requêtes | Temps de génération de la page : Total (SQL) 0.0475s (0.0351s)