1.3 Créer une classe Objective-C et l’utiliser

Introduction

Tout développeur objet se doit de créer des classes. Celles-ci sont des mécanismes d’implémentation, c’est à dire contenant du code et des données. Objective-C permet la création de classes. Ces dernières sont organisées en créant 2 fichiers pour chaque classe : le fichier déclaratif : MaClasse.h et le fichier contenant le code : MaClasse.m. Si vous développez sous MAC vous pouvez créer des fichiers d’implémentations : *.mm, qui permettent de mélanger de l’Objective-C et du C++ (Objective-C++).

Version XCode utilisée : 4.6.2

Sommaire de l’article

1. Créer la déclaration et l’implémentation de la classe
2. Ajouter une méthode dans le .h
3. Ajouter la méthode dans l’implémentation
4. Créer une méthode privée
5. Ajouter une méthode statique
6. Créer une instance
7. Créer un constructeur et un destructeur

1. Créer la déclaration et l’implémentation de la classe

Pour créer une classe en Objective-C on crée 2 fichiers : un *.h et *.m. Considérons pour notre exemple la création d’une classe LTMPoint, contenant quelques attributs et quelques messages. Au cours de cet article, j’utilise XCode l’IDE Apple pour développer.

J’ajoute ici un fichier avec XCode du type Objective-C
creation classe 1

Notre classe s’appelera LTMPoint
creation classe 2

Les 2 fichiers dans notre projet
projet XCode

XCode a crée un fichier déclaratif : LTMPoint.h

#import <Foundation/Foundation.h>

@interface LTMPoint : NSObject
 //...
@end

Le fichier LTMPoint.h contient la commande de pré processing permettant l’importation de Foundation.h qui contient les classes de base. Le mot clé @interface en Objective-C est présent pour désigner l’interface de la classe et non pas l’interface au sens POO ou en Java par exemple. L’équivalent de l’interfaces en POO est appelé protocole en Objective-C. On constate ici que la classe LTMPoint hérite de la classe de base de l’architecture NSObject.

Les mots clés @interface et @end délimitent les membres de la classe.

XCode a crée aussi un fichier pour le code : LTMPoint.m

#import "LTMPoint.h"

@implementation LTMPoint
  //...
@end

Le fichier LTMPoint.m contient les mots clés @implementation et @end. Entre ces deux bornes sera crée le code des méthodes.

2. Ajouter une méthode dans le .h

@interface LTMPoint : NSObject
    // Ajout de propriétés
    @property double x;
    @property double y;

    // Ajout d'une méthode
    -(void) setXY:(double)xx:(double)yy;
@end

Les propriétés

Le mot clé @property permet de créer automatiquement : un attribut double x, accompagné de ses accesseurs (et y aussi). Autrement dit le compilateur créera automatiquement les messages setX: et getX: pour la propriété x. Il est à noter que cette propriété étant déclarée dans l’interface est implicitement publique. Elle sera vue par les utilisateurs de cette classe sous la forme de x, dans notre implémentation elle sera vu comme _x (convention Apple).

Note : Dans cette version d’XCode, il n’est plus nécessaire de rajouter le mot @synthesize pour cette propriété : Apple simplifie régulièrement la syntaxe du langage.

Le message

-(void) setXY:(double)xx:(double)yy;

On constate en retourne -(void) : le signe – signifie qu’il s’agit d’une méthode d’objet et non pas de classe (signe + pour les méthodes statiques).
Le nom de la méthode est setXY
Elle passe attend 2 paramètres : 2 doubles, xx et yy.

3. Ajouter la méthode dans l’implémentation

@implementation LTMPoint

-(void) setXY:(double)xx :(double)yy {
    _x = xx;
    _y = yy;
}

@end

Le code du message setXY: met à jour les attributs. On remarque ici que l’on voit la propriété x comme étant _x, et ce implicitement.

4. Créer une méthode privée

@interface LTMPoint ()
    // Mettre ici les membres privés
    -(void)messagePrivate;
@end

@implementation LTMPoint
    -(void)messagePrivate {
        // ...
    }

    -(void) setXY:(double)xx:(double)yy {
        _x = xx;
        _y = yy;

        // Appel d'un message privé
        [self messagePrivate];
    }
@end

Pour créer un membre privé en Objective-C il suffit de ne pas le déclarer dans le fichier header. On déclare les membres privés dans le fichier *.m en utilisant une syntaxe comme ci-dessus @interface LTMPoint(). Dans cette dernière il suffit de déclarer les membres privés. Ces derniers ne figurant pas dans le fichier header ils seront privés à notre classe. Ici dans votre exemple on constate également l’appel à un message privé [self messagePrivate];

5. Ajouter une méthode statique

Fichier LTMPoint.h

@interface LTMPoint : NSObject
    // ...
    +(LTMPoint*)createPoint;
@end

Fichier LTMPoint.m

@implementation LTMPoint
    +(LTMPoint*) createPoint {
        return [[[LTMPoint alloc]init] autorelease];
        // création d'un point
    }
    // ...
@end

On ajoute ci-dessous une méthode, un message statique. Pour ce faire devant le message on indique le signe +. Ce message retourne un point qui est alloué. alloc permet l’allocation mémoire de l’objet, autrement dit réserve la place occupée en mémoire. init est l’appel du constructeur par défaut. autorelease est un mot clé qui place cet objet dans une bassine spéciale, l’objet sera libéré par Objective-C à lafin du cycle de vie du thread courant.

6. Créer une instance

[[LTMPoint alloc]init];

Pour créer une instance en Objective-C, autrement dit un objet, on utilise un l’allocateur alloc, puis on appelle le constructeur init. Il est à noter qu’un constructeur en Objective-C démarre par init. On peut imaginer un second constructeur, cette fois surchargé qui serait initXY:.

Si ce dernier n’est pas crée dans votre classe, c’est celui de la super classe qui sera appelé. La syntaxe [[ peut sembler déroutante pour le débutant mais permet tout simplement d’enchainer les appels de messages.

En Java on aurait écrit : LTMPoint.alloc().init();.

7. Créer un constructeur et un destructeur

Fichier LTMPoint.h

@interface LTMPoint : NSObject
    // constructeur par défaut
    -(id) init;
    // constructeur surchargé
    -(id) initXY: (double)xx : (double)yy;
@end

Fichier LTMPoint.m

@implementation LTMPoint
    // constructeur par défaut
    -(id) init {
        self = [super init]; // init à faire ici return self;
    }
    // constructeur surchargé
    -(id) initXY : (double)xx: (double)yy {
        self = [super init];
        _x = xx;
        _y = yy;
        return self;
    }
@end

Les constructeurs

Ci-dessus 2 constructeurs ont été ajoutés dans la classe. L’un sera appelé sans paramètre : c’est le constructeur par défaut : [[LTMPoint alloc]init]. L’autre est un constructeur attendant 2 paramètres : x et y. Son appel ressemblera à ce code : [[LTMPoint alloc]initXY:1.0 :2.0].

On remarque que l’implémentation correcte du constructeur prévoit l’appel du constructeur de la super classe : [super init], l’adresse récupérée est assignée sur self qui représente l’adresse de notre objet. Le type de retour du constructeur est du type id qui représente en Objective-C l’adresse d’un objet.

Le destructeur

@implementation LTMPoint
    -(void)dealloc {
        // libération ici
        [super dealloc];
    }
@end

Le destructeur est dealloc et retourne void. On appelle également le code de la classe mère et on libère les données.

A noter : Si vous codez sur MAC avec l’ARC le destructeur est obsolète.

Conclusion

Cet article basique doit vous permettre de comprendre la création des classes, l’ajout d’attributs et de messages, la gestion des membres privés et les constructeurs et destructeurs.

J’espère que cet article vous a plu, n’hésitez pas à le communiquer à vos collègues et cliquant sur les boutons ci-dessous.

Au sujet du formateur

bertrand

Bertrand Leclercq

Anime la formation ONE et PAD sur iOS chez ORSYS et la formation Introduction aux mobiles (Android/iOS) chez Dassault Systèmes

Contacter le formateur
Catégories
4 Comments
  1. Patrick

    Un grand merci Bertrand, tout est expliqué clairement, et les références au Java sont top !
    (je viens justement de la POO en Java, et donc ça me parle)

    J’ai enfin pu comprendre le « @interface MaClasse () » que j’avais pris pour un contructeur alors que c’est un morceau qui décrit l’encapsulation « private »

  2. Patrick

    Un grand merci Bertrand, tout est expliqué clairement, et les références au Java sont top !
    (je viens justement de la POO en Java, et donc ça me parle)

    J’ai enfin pu comprendre le « @interface MaClasse () » que j’avais pris pour un contructeur alors que c’est un morceau qui décrit l’encapsulation « private »

    NB : Par contre problème de script sur ce site (bug sur trois navigateurs)

0 Pings & Trackbacks

Laisser un commentaire