Apprendre Objective-C Jour 4

Bienvenue à la quatrième partie de cette série sur Objective-C. Jusqu'ici, nous avons beaucoup étudié la théorie, les principes et les fonctionnalités du langage pour bien comprendre son fonctionnement. Aujourd'hui, nous allons créer une classe simple similaire à l'exemple de voiture que nous avons examiné dans les parties précédentes de cette série. Notre classe prendra les détails d'une voiture, ce qui nous permettra d'obtenir et de définir les valeurs retenues. Après l'exemple d'aujourd'hui, vous devriez pouvoir créer vos propres classes dans Xcode et les manipuler..

Jusqu'à présent, nous avons eu d'excellents commentaires par e-mail, Twitter et des commentaires. C’est formidable de voir autant de personnes s’intéresser à ce sujet et c’est encore mieux de voir que tant d’entre vous l’essaient et posent de bonnes questions. Continuez!

Commencer

Commencez par lancer Xcode et créer un nouveau projet. Sous le séparateur Mac OS X, cliquez sur Application, puis sur Outil de ligne de commande. Enfin, modifiez le menu déroulant pour définir le type sur Fondation..

Enregistrez le projet comme vous le souhaitez, j’ai appelé le mien CarApp. Une fois que la fenêtre du projet apparaît, nous devons créer une nouvelle classe. Appuyez sur Commande-N (ou Fichier> Nouveau fichier), accédez à la classe Cacao sous Mac OS X et sélectionnez la classe Objective-C. Assurez-vous que Sous-classe de est défini sur NSObject et appuyez sur Suivant. Nommez votre classe SimpleCar et assurez-vous qu'un fichier .h sera créé, puis enregistrez-le..

Notre classe existe maintenant, mais elle ne fait rien. Changeons cela en lui donnant du code. N'oubliez pas que dans Objective-C, nous divisons notre code en deux parties: interface et implémentation. Il est logique de commencer par travailler sur l'interface, c'est donc là que nous allons commencer.

Codage de l'interface

Ouvrez le fichier SimpleCar.h et dans son état actuel, il devrait ressembler à ceci (j'ai omis l'en-tête de commentaire ci-dessous)

 #importation  @interface SimpleCar: NSObject  @end 

Premièrement, nous incluons Cocoa.h, qui nous donne accès à des éléments tels que NSString, NSMutableString, etc. Ensuite, nous créons notre classe (SimpleCar) en tant que sous-classe de NSObject..

Nous devons maintenant décider des informations que notre classe doit stocker. Puisque nous utilisons une voiture comme exemple, nous devons stocker des informations relatives à la voiture, telles que:

  • Faire
  • Modèle
  • NIV

Nous pourrions aller beaucoup plus loin, mais pour le moment, ça ira. Pour chacune de ces propriétés, nous devons les stocker dans une variable adaptée à ce type de données. Marque et modèle seront une gamme de caractères (tels que texte, nombre et éventuellement ponctuation), il est donc logique d'utiliser une chaîne. Le numéro d'identification du véhicule (VIN) ne sera qu'un numéro, c'est ce que nous allons utiliser. Notre code ressemble maintenant à ceci (en-tête omis):

 @interface SimpleCar: NSObject NSString * make; Modèle NSString *; NSNumber * vin;  @fin 

Nous avons dit précédemment que pour obtenir ou définir les données d'une classe, une méthode devrait être utilisée. Donc, pour définir les variables, nous devons ajouter des méthodes. Pour ce faire, nous en créerons quatre: un définira la marque, un le modèle, un le VIN et une dernière méthode définira les deux méthodes make AND (juste pour vous montrer comment utiliser plusieurs arguments)..

 @interface SimpleCar: NSObject NSString * make; Modèle NSString *; NSNumber * vin;  // définir les méthodes - (void) setVin: (NSNumber *) newVin; - (void) setMake: (NSString *) newMake; - (void) setModel: (NSString *) setModel; // méthode pratique - (void) setMake: (NSString *) newMake andModel: (NSString *) newModel; @fin 

Nous déclarons des méthodes après l'accolade et avant @end. En plaçant un tiret (signe moins) avant la méthode, nous indiquons au compilateur que nous sommes sur le point de déclarer une méthode d'instance. Une méthode d'instance est une méthode exécutée sur notre instance. Inversement, un signe plus indique que la méthode appelée est une méthode de classe qui ne nécessite pas d'instance d'objet individuel pour s'exécuter, à plus tard.

Notre première méthode retourne void, s'appelle setVin et prend un NSNumber en argument. Notre deuxième méthode est similaire, elle retourne void, appelle callMake et prend un argument NSString. Le troisième est le même, avec un nom différent.

Notre méthode finale renvoie également null mais prend deux paramètres: newMake et newModel, qui doivent tous deux être NSString. La dénomination utilisée dans cette méthode est similaire à la façon dont la plupart des méthodes Objective-C sont nommées: en clair. Ainsi, lorsque vous lisez la méthode autorisée, il est évident que la méthode "Définira la marque et le modèle". Il est important de se rappeler que le nom de la méthode dans ce cas est 'setMake: andModel:' - tous les titres d'argument sont inclus dans le nom de la méthode..

Une note importante est que nous utilisons (void) car nos méthodes n'ont pas besoin de renvoyer quoi que ce soit. Comme ils ne font que paramétrer les données et qu’ils n’ont rien à renvoyer (comme un message de réussite), nous utilisons simplement void.

Ensuite, nous allons ajouter les méthodes que nous allons utiliser pour obtenir les valeurs. Bien que nous appelions nos méthodes get et set, nous n'utilisons généralement que "set" dans le titre et omettons "get". Comment vous nommez vos méthodes est finalement à vous, mais laisser tomber "get" est commun et aide à éviter la confusion.

Notre nouvelle série de méthodes ressemble à ceci:

 // méthodes set - (void) setVin: (NSNumber *) newVin; - (void) setMake: (NSString *) newMake; - (void) setModel: (NSString *) newModel; // méthode pratique - (void) setMake: (NSString *) newMake andModel: (NSString *) newModel; // récupère des méthodes - (NSString *) make; - modèle (NSString *); - (NSNumber *) vin; 

Notez que les méthodes get utilisent les mêmes noms que les variables de la classe. Cela simplifiera la tâche lorsque nous récupérerons les variables. Ce sera comme si nous accédions aux variables directement, ce qui donnait essentiellement l'impression que les méthodes get étaient transparentes..

Coder la mise en oeuvre

Alors, maintenant que l'interface est en place et que nous savons ce que la classe fera, nous devons implémenter nos méthodes. En regardant en arrière, nous avons quatre méthodes à implémenter: setVin, setMake, setModel et setMake: andModel. Avant de déplacer des fichiers, copiez les déclarations de méthode dans votre presse-papiers (Cmd + C). Maintenant, fermez SimpleCar.h et lancez SimpleCar.m dans l'éditeur, en collant les déclarations de méthode entre @implementation et @end, comme suit:

 @implementation SimpleCar // set method - (void) setVin: (NSNumber *) newVin; - (void) setMake: (NSString *) newMake; - (void) setModel: (NSString *) newModel; // méthode pratique - (void) setMake: (NSString *) newMake andModel: (NSString *) newModel; // récupère des méthodes - (NSString *) make; - modèle (NSString *); - (NSNumber *) vin; @fin 

Évidemment, cela n’est pas correct. Nous devons donc remplacer les points-virgules par des accolades, dans lesquelles le fonctionnement interne de la méthode ira, comme ceci:

 @implementation SimpleCar // set method - (void) setVin: (NSNumber *) newVin  - (void) setMake: (NSString *) newMake  - (void) setModel: (NSString *) newModel  - (void) setMake: (NSString *) newMake andModel: (NSString *) newModel  // obtenir des méthodes - (NSString *) make  - (NSString *) modèle  - (NSNumber *) vin  @end 

Nous devons maintenant donner du code à nos méthodes. Commençons par les méthodes getter, car elles sont assez simples. Pour chaque méthode getter, il suffit de s’assurer que la fonction renvoie ce qu’elle est destinée à renvoyer. Pour cette raison, nos méthodes de lecture ressemblent à ceci:

 - (NSString *) make return make;  - (NSString *) modèle modèle de retour;  - (NSNumber *) vin return vin;  

Rappelles toi: les méthodes renvoient les variables que nous avons définies dans le fichier d'interface. Ne vous trompez pas entre les noms de méthodes et les noms de variables.

C'est assez simple, lorsque nous appelons make (par exemple), puis retourne le pointeur sur une chaîne NSString - dans ce cas, à la variable make. Il en va de même pour model et vin (sauf que vin retourne un nombre).

Maintenant, pour les méthodes de définition, nous allons d'abord examiner le code, puis nous l'examinerons par la suite. Nos méthodes de setter ressemblent à ceci:

 // méthodes set - (void) setVin: (NSNumber *) newVin [publication du vin]; vin = [[NSNumber alloc] init]; vin = newVin;  - (void) setMake: (NSString *) newMake [make release]; make = [[NSString alloc] initWithString: newMake];  - (void) setModel: (NSString *) newModel [version du modèle]; modèle = [[NSString alloc] initWithString: newModel];  // méthode pratique - (void) setMake: (NSString *) newMake etModel: (NSString *) newModel // Réutilise nos méthodes de plus tôt [self setMake: newMake]; [self setModel: newModel];  

Les méthodes set sont un peu plus délicates que nos méthodes get. Nous voulons affecter les valeurs qui sont transmises à chaque méthode afin qu'elles appartiennent à la classe. Nous libérons d'abord ces variables au cas où elles sont déjà allouées. S'ils ne sont pas alloués, ils sont nuls et les objets nil ignorent les messages qui leur sont transmis. Nous aborderons davantage ces questions lorsque nous aborderons la gestion de la mémoire.

Comme nous avons effectivement alloué de la mémoire pour nos objets dans les méthodes de définition, nous devons nous assurer de les libérer lorsque l'objet est libéré de la mémoire. Pour ce faire, nous devons ajouter une méthode dealloc personnalisée, comme suit:

 -(vide) dealloc [libération du vin]; [faire un communiqué]; [version du modèle]; [super dealloc];  

Tester la classe

Toutes nos félicitations! Si vous avez suivi tout ce qui précède, vous devriez maintenant avoir une classe ouvrière (sinon, téléchargez les fichiers sources disponibles avec cet article). Alors testons-le.

Ouvrez le fichier principal de votre projet (le mien s'appelle CarApp.m) qui devrait ressembler par défaut à quelque chose comme:

 #importation  int principal (int argc, const char * argv []) NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; // Insère le code personnalisé ici… NSLog (@ "Hello, World!"); [drain de piscine]; retourne 0;  

Supprimez le commentaire et la ligne NSLog car nous n'en aurons plus besoin maintenant.

Pour commencer à utiliser notre classe, nous devons l'intégrer au programme. Sous la ligne #import originale, ajoutez la ligne suivante:

 #import "SimpleCar.h" 

Notre classe est maintenant disponible pour utilisation, mais nous devons en créer une instance afin de la tester. Voici le code utilisé au total:

 #importation  #import "SimpleCar.h" int main (int argc, const char * argv []) NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; SimpleCar * myCar = [[SimpleCar alloc] init]; NSNumber * newVin = [NSNumber numberWithInt: 123]; [myCar setVin: newVin]; [myCar setMake: @ "Honda" andModel: @ "Civic"]; NSLog (@ "La voiture est:% @% @", [myCar make], [myCar model]); NSLog (@ "Le vin est:% @", [myCar vin]); [version myCar]; [drain de piscine]; retourne 0;  

Tout d'abord, nous créons un pointeur sur une instance de SimpleCar appelée myCar. Ensuite, nous utilisons alloc et init - nous en discuterons plus tard..

Ensuite, puisque nous devons passer un NSNumber à la méthode setVin, nous en créons un ici. De nouveau, nous créons un pointeur sur une instance de NSNumber appelée newVin et l'initions avec la valeur entière égale à 123. La constante '123' est un entier, raison pour laquelle nous utilisons numberWithInt..

Ensuite, nous invoquons nos méthodes. Nous définissons d'abord qui doit recevoir le message (myCar), puis nous utilisons la méthode setVin. Après les deux points, nous fournissons la valeur à la méthode, qui est le NSNumber que nous avons créé auparavant. Ensuite, nous faisons la même chose mais appelons la méthode setMake avec deux paramètres. La raison pour laquelle ces paramètres sont précédés du signe @ est pour indiquer au compilateur que ce qui suit est une chaîne.

Enfin, nous publions myCar au fur et à mesure que nous en avons terminé - plus à ce sujet plus loin dans la série sous gestion de la mémoire.

Notre classe fonctionne maintenant et, afin de voir la preuve, nous avons ajouté des instructions NSLog pour imprimer les valeurs sur la console. Si vous ouvrez la console (Exécuter> Console), puis construisez et exécutez votre application, vous devriez voir une sortie similaire à celle-ci:

Propriété et synthèse

Si vous regardez le code ci-dessus, une grande partie semble assez inutile et excessive. Par exemple, dans nos méthodes de lecture, tout ce que nous faisons consiste à renvoyer une variable d'instance - mais cela prend trois lignes de code pour faire quelque chose de simple. De plus, dans nos méthodes de définition, nous ne faisons que définir des variables d'instance - essentiellement toutes nos méthodes, à l'exception de notre méthode qui prend deux arguments, semble être surestimée et gênante. Objective-C résout ce problème avec @property et @synthesize, qui remplacent nos méthodes d'accès et permettent un codage beaucoup plus net..

Voici à quoi ressemble notre nouveau fichier d'interface à l'aide de propriétés:

 #importation  @interface SimpleCar: NSObject NSString * make; Modèle NSString *; NSNumber * vin;  @property (readwrite, keep) NSString * make; @property (readwrite, keep) modèle NSString *; @property (readwrite, keep) NSNumber * vin; // méthode pratique - (void) setMake: (NSString *) newMake andModel: (NSString *) newModel; @fin 

Wow, c'est vraiment beaucoup plus court. Alors que se passe-t-il avec les déclarations @property? Tout d'abord, nous disons au compilateur que nous déclarons une propriété en utilisant @property, puis nous suivons avec des attributs pour cette propriété. Les attributs sont l'état de lecture / écriture d'une propriété et une partie de la gestion de la mémoire. Nous avons utilisé readwrite pour tout, ce qui signifie que les méthodes getter et setter sont créées de manière dynamique pour nos variables d'instance (nous pourrions utiliser writeonly ou readonly pour seulement l'une ou l'autre). La raison pour laquelle nous utilisons l'option Retenir apparaîtra clairement la prochaine fois que nous couvrirons la gestion de la mémoire..

Avant que cela puisse fonctionner, nous devons l'implémenter dans notre fichier d'implémentation à l'aide de @synthesize. Notre nouveau fichier d'implémentation ressemble à ceci:

 #import "SimpleCar.h" @implementation SimpleCar @synthesize marque, modèle, vin; - (void) setMake: (NSString *) newMake etModel: (NSString *) newModel [self setMake: newMake]; [self setModel: newModel];  @fin 

Ça n'a pas l'air mieux? Pensez-y comme ceci: @property remplace toutes les déclarations de méthode d'interface pour les getters et les setters, et @synthesize remplace les méthodes réelles elles-mêmes. Les getters et les setters sont maintenant créés de manière dynamique et nous n'avons pas besoin de perdre du temps à les créer à moins de devoir faire quelque chose de vraiment spécial..

Emballer

Vous devez maintenant avoir une emprise solide sur les classes, les objets et les instances. Bien sûr, vous ne créez pas de cours qui vont changer le monde, mais cela prend du temps. Il est préférable d'apprendre par l'exemple. Si vous ne codez pas au fur et à mesure, veillez au moins à télécharger les fichiers source et à en faire une lecture (et une compilation) pour vous assurer que vous êtes à 100% de ce qui se passe..

La prochaine fois

Nous avons beaucoup parlé de la gestion de la mémoire dans ce didacticiel, c’est un sujet très important qui doit être traité (jeu de mots voulu), nous y reviendrons donc plus tard. Certes, ce n'est pas le sujet le plus amusant ou le plus facile à comprendre, mais il est absolument essentiel de devenir un programmeur expérimenté en Objective-C..

Défi

Le défi de cette semaine peut être un peu délicat, mais nous verrons comment vous allez. Tout d'abord, si vous n'avez pas copié tout le code ci-dessus, téléchargez les fichiers source inclus dans cet article. Le défi consiste à ajouter une autre classe au projet, mais cette fois, il devrait s'agir d'une sous-classe de SimpleCar (rappelez-vous, nous définissons la classe parente dans le fichier d'interface). Si vous pouvez le faire, jouez avec les méthodes héritées, utilisez-les et essayez d'ajouter les vôtres pour des éléments tels que: la taille du moteur, les portes ou la hauteur..

Rappelles toi: si vous avez des questions, posez un commentaire ci-dessous ou envoyez-moi un message sur Twitter. La seule question stupide est celle que vous n'avez pas posée - cette série est consacrée à l'apprentissage, alors n'hésitez pas à demander plus loin.!