I. Classes d'objets et héritage▲
Java comme Objective-C sont des langages objet. Comme beaucoup des langages de cette famille, ils dépendent d'un système de classe.
Cet article présente la syntaxe de création d'une classe en Objective-C, en la comparant avec celle de Java.
I-A. Le rôle d'une classe▲
La classe est un moule à partir duquel on peut construire des objets : les instances d'une classe.
La classe couvre différents objectifs dont les plus significatifs sont :
- définir les données manipulées par un objet ;
- définir les services fournis par un objet ;
- masquer les détails d'implémentation en encapsulant les données et les services techniques.
Donnée |
Service |
---|---|
attribut, propriété, variable |
méthode, message |
Une classe peut atteindre ses objectifs en s'appuyant sur des outils techniques :
- des règles de visibilité pour définir qui peut voir ses attributs et méthodes ;
- l'héritage définit la généalogie d'une classe ;
- le polymorphisme pour se restreindre à utiliser une interface plutôt qu'une implémentation spécifique.
I-B. Comment créer une classe ?▲
La méthode la plus simple pour commencer est de créer un projet de type Foundation Tool dans la famille Command Line Utility.
Pour créer une classe, utilisez l'assistant de création :
- allez dans le menu File, entrée New File…
- choisissez alors dans le groupe Cocoa l'entrée Objective-C Class ;
- donnez un nom à votre classe.
XCode vous crée un squelette de classe vide sous la forme de deux fichiers. Dans mon cas, j'ai créé la classe SimpleClass :
- SimpleClass.h définit l'interface de ma classe ;
- SimpleClass.m contiendra l'implémentation de ma classe.
Les nouveaux fichiers apparaissent dans le groupe du projet sur la gauche. Je les ai déplacés dans le groupe « Source » pour mieux organiser mon projet.
La première différence par rapport à Java saute aux yeux : là où Java mélange dans un fichier unique interface et implémentation, Objective-C sépare les deux dans des fichiers indépendants.
Cette séparation est un héritage direct du langage C au-dessus duquel est construit Objective-C. L'avantage de cette solution est de pouvoir utiliser une classe sans disposer de son code source. Le fichier en-tête est suffisant pour le compilateur et décrit l'ensemble de l'interface publique de la classe et de ses objets.
L'interface d'une classe est définie dans le fichier d'en-tête .h(2)
#
import
<Cocoa/Cocoa.h>
@interface
SimpleClass : NSObject
{
// Déclaration des attributs associés à la classe
}
// Déclaration des méthodes associées à la classe
@end
L'implémentation de la classe est dans un fichier .m(3)
#
import
"SimpleClass.h"
@implementation
SimpleClass
// Implémentation des différentes méthodes
// déclarées dans le fichier en-tête
@end
La directive #import indique au compilateur qu'il lui faut inclure le fichier en-tête indiqué. Ainsi, l'implémentation de notre classe importe le fichier en-tête qui lui est associé.
En Java le code aurait été réduit à un simple fichier .java :
public
class
SimpleClass {
// Définitions des attributs et méthodes
}
Deux outils indispensables à connaître :
- Dans la barre d'outils, le bouton pour passer dans l'éditeur pour le fichier sélectionné ;
- Dans l'éditeur, en haut à gauche, un bouton en forme de double carré permet de passer de l'interface à l'implémentation et inversement.
En résumé, une classe se déclare ainsi :
Java |
Objective-C |
---|---|
Sélectionnez
|
Sélectionnez
|
I-C. Étendre une classe▲
Objective-C supporte le même modèle d'héritage que Java, à savoir une seule classe mère pour une classe donnée.
Contrairement à Java, il n'existe pas une hiérarchie unique pour la généalogie des classes. Au contraire, toute nouvelle classe peut former la racine d'une nouvelle arborescence de classes.
Le squelette de classe généré par XCode indique automatiquement que votre nouvelle classe dérive de la classe racine de Cocoa NSObject. Hériter de NSObject n'est donc qu'une facilité et en aucun cas une obligation. Cependant, le type d'objet par défaut ne définit aucun comportement, ce qui fait que Objective-C dépend très fortement du framework applicatif utilisé.
@interface
SimpleClass : NSObject
{
...
Ce qui en Java aurait pu s'écrire :
public
class
SimpleClass extends
java.lang.Object {
...
Mais en Java, toute classe dérivant obligatoirement de la classe Object, cet héritage n'est généralement pas spécifié explicitement par les développeurs. Cette facilité devra être évitée à tout prix en Objective-C sous peine de voir son code ne pas réussir à fonctionner correctement.
Pour manipuler des objets, le langage Objective-C utilise le type id qui est une référence sur un objet de type indéterminé.
Même si le langage permet des arbres de classes distincts de celui dont la racine est NSObject, il est fortement déconseillé de se construire sa propre hiérarchie de classes. Objective-C n'a que peu d'intérêt s'il n'est pas utilisé avec le framework Cocoa, et dériver ses classes à partir de NSObject est le meilleur moyen pour en profiter (4)
Si l'héritage simple peut paraître trop limité par rapport à un modèle d'héritage multiple tel que celui proposé par C + +, nous verrons que comme en Java, Objective-C utilise la notion d'interface. Cela permet sans compromettre la simplicité de supporter des modèles complexes.
Héritage |
Java |
Objective-C |
---|---|---|
Classe Racine |
java.lang.object |
NSObject (par facilité, mais pas forcément) |
Déclaration |
class MaClasse extends ClasseMere |
@interface MaClasse : ClasseMere |
Héritage Implicite |
Oui, de java.lang.Object |
Non |
I-D. Pour finir▲
Nous savons maintenant définir une classe.
Cette classe ne nous sert pas à grand-chose pour l'instant et il nous reste encore quelques étapes avant de la rendre réellement utilisable :
- pour les instances ;
- (services) proposés par les objets ;
- de cette classe.