III. Définir les méthodes d'une classe▲
Les méthodes permettent de masquer les variables et exposent l'interface publique d'un objet ou d'une classe.
Comme Java, Objective-C connaît les méthodes d'instance et de classe, mais son interprétation du modèle objet diffère de Java.
III-A. Généralités▲
Java parle volontiers de méthode et Objective-C adopte plutôt la terminologie de message.
Cette différence dépasse le vocabulaire et reflète une réalité concrète. Les services des objets ne sont effectivement pas des appels vers des fonctions, mais des envois de messages qui sont ensuite traités par une fonction. La différence est subtile, mais peut aider à comprendre l'esprit du langage.
Là où Java se rapproche de C + +, Objective-C est vraiment dans l'esprit de SmallTalk par cette idée de message. Le coût est limité au moteur du langage (5).
Le diagramme ci-dessous illustre comment un message peut-être géré par un objet.
- La classe déclare les messages qu'elle gère.
- La classe déclare les messages gérés par ses instances.
- Les instances ou la classe reçoivent des messages correspondant à ce que la classe a déclaré.
- Les messages de classe sont gérés par l'implémentation fournie par la classe.
- Les messages d'instance sont gérés par l'implémentation fournie par l'objet.
C'est en partie cette dernière caractéristique qui explique que les méthodes, contrairement aux variables, ne bénéficient pas de règles de visibilité. Les méthodes sont soit des méthodes d'instance, soit des méthodes de la classe.
Mais comme pour les variables de classe, le module peut servir à implémenter des messages privés. Il suffit de définir une méthode répondant à un message dans l'implémentation, sans déclarer ce message au niveau de l'interface de l'objet. Mais même si le message n'est pas visible il peut toujours être envoyé par un objet qui n'a pas connaissance de l'implémentation privée. Je ne pense pas que cette pratique soit à conseiller.
- Java définit des méthodes sur les objets ou les classes. Une méthode Java est une fonction qui utilise la portée (l'espace de nommage) de la classe qui l'a définie.
- Objective-C définit les services d'une classe par un ensemble de messages auxquels elle est capable de répondre. La classe répond à un message en appelant une méthode.
Le mode de fonctionnement d'Objective-C permet d'introduire une forte dynamique dans le langage sans imposer le surcoût important d'un système d'introspection.
Une classe peut ainsi répondre à un message sans forcément implémenter la méthode qui y répondra. Il est très facile de déléguer la gestion du message à un objet tiers en lui faisant simplement suivre le message.
III-B. Déclaration des messages▲
Comme toutes les déclarations d'une classe, les messages gérés par une classe sont déclarés dans le fichier en-tête de la classe.
@interface
SimpleClass : NSObject
{
// ...
}
// Constructeur
-
(
id
) init;
// Affichage
-
(
NSString
*
) description;
// Accès et modification sur 'destination'
-
(
id
) destination;
-
(
void
) setDestination: (
id
) location;
// Accès et modification sur 'speedLimit'
-
(
int
) speedLimit;
-
(
void
) setSpeedLimit: (
int
) speed;
// Une méthode de classe
+
(
id
) cloneSimpleObject: (
id
) object;
@end
Une déclaration se décompose en trois types d'éléments :
-
Un préfixe :
- Un signe moins - pour les messages gérés par les instances,
- Un signe plus + pour les messages gérés par la classe ;
- Le type de retour de chaque message ;
- Le nom du message ;
- Si le message accepte un paramètre, il est déclaré en indiquant son type et un identifiant.
Un message peut accepter plusieurs paramètres, dans ce cas la syntaxe varie largement du Java. Par exemple, pour déclarer un constructeur qui permet de définir les valeurs des variables d'instance, on peut utiliser la déclaration suivante :
-
(
id
) initWithDestination: (
id
) location andSpeedLimit: (
int
) limit;
Dans cet exemple, le nom du message est initWithDestination:andSpeedLimit : et les deux paramètres sont location et limit. L'avantage de cette syntaxe est simple : le nom des méthodes, s'il est correctement choisi, permet d'expliciter le rôle de chaque paramètre.
En Java, le rôle de chaque paramètre ne peut être déduit que si votre éditeur offre une complétion automatique et un accès à la Javadoc au fils de l'écriture de votre code. Cela est utile lorsque vous écrivez votre code, mais absent lorsque vous le relisez.
En Objective-C, le langage permet d'exposer directement le rôle des paramètres, que vous soyez en pleine écriture du code ou en train de relire un source vieux de plusieurs mois. Le code source est autosuffisant pour assurer sa compréhension.
III-C. Définition des méthodes▲
Les méthodes qui répondent aux messages déclarés dans l'interface de la classe sont définies dans le module d'implémentation de la classe.
Pour chaque message, on définit une méthode :
@implementation
SimpleClass
//...
-
(
int
) speedLimit
{
return
speedLimit;
}
-
(
void
) setSpeedLimit: (
int
) speed
{
speedLimit =
speed;
}
//...
@end
Si vous ne fournissez pas de méthode pour chaque message déclaré, votre classe est abstraite.
III-D. Appel de méthode▲
Pour invoquer un service sur un objet ou une classe, il suffit de lui envoyer le message correspondant :
// Message sans paramètre
[object message];
/* Appelle le message messageD:situeA:
* avec les paramètres expediteur et lieu
*/
[objet messageDe: expediteur situeA: lieu]
Voici par exemple l'implémentation de la méthode description pour notre classe simple :
-
(
NSString
*
) description;
{
NSMutableString
*
descr =
[[NSMutableString
alloc] initWithString: @"SimpleClass"
];
if
(
nil
!=
[self
destination] ) {
[descr appendFormat: @" destination %@"
, [self
destination]];
}
[descr appendFormat: @" speedLimit %d"
, [self
speedLimit]];
return
descr;
}
III-E. Pour finir▲
Nos objets viennent d'acquérir la capacité de proposer des services. Ils sont donc largement plus utiles.
Il nous manque un dernier élément : comprendre le cycle de vie des objets pour pouvoir les animer correctement. C'est le sujet de cette introduction.