les objets C# |
Nous
allons dans ce chapitre revenir à un peu plus de théorie
afin de mieux comprendre ce qui a été fait dans le
dernier cours et éclaircir les points obscurs. |
Sommaire1. Les constructeurs : générateurs d'objets 4. Retenir les objets : les handles 5. Créer un handle dans un programme |
Lorsque
nous avons abordé le concept de la programmation orientée
objet dans la première partie de ce livre, nous avons
appris qu'une classe pouvait être assimilée à
un moule à partir duquel nous pouvions générer
autant d'objets aux caractéristiques différentes que
nous le voulions. Pour créer un objet à partir d'une
classe, cette dernière doit disposer d'une méthode
spéciale qu'on appelle constructeur. |
Revenons sur le programme que nous avons écrit dans le dernier chapitre. Nous allons changer notre nom de classe en SecondProgramme et nous allons ajouter dans le fichier une classe que nous allons nommer Chien : |
//SecondProgramme.cs /**************************************************/ /* */ /* second programme d'apprentissage du C# */ /* (premiere version) */ /* Valentin BILLOTTE - " Le langage C # " 2001 */ /* */ /**************************************************/ //utiliser le namespace System using System ; /** * objet qui contient notre fonction main */ class SecondProgramme { /** * méthode principale de notre programme */ public static void Main() { Console.Out.WriteLine("Nous n'avons pas encore créé de chien"); } } /** * classe qui permet la création d'un objet de type Chien */ class Chien { //chien ne dispose pour l'instant d'aucun membre } |
Donnez
le nom SecondProgramme.cs à votre fichier source et
compilez. |
/** * classe qui permet la création d'un objet de type Chien */ class Chien : object { /** * constructeur */ Chien() { //la méthode ne fait rien pour l'instant } } |
Le
constructeur Chien() respecte toutes les conventions que nous
avons énoncées : la méthode porte le nom de
la classe et est terminée par des parenthèses. Un
constructeur n'a pas à renvoyer de valeur comme c'est le
cas pour une méthode standard, nous n'indiquerons donc pas
avant son nom si elle renvoie ou non une donnée. |
Nous
savons que c'est le constructeur de la classe Chien : Chien() qui
va être à l'origine de la création de l'objet.
Il nous manque maintenant la syntaxe nécessaire à
cette action. |
//SecondProgramme.cs /**************************************************/ /* */ /* second programme d'apprentissage du C# */ /* (seconde version) */ /* Valentin BILLOTTE - " Le langage C # " 2001 */ /* */ /**************************************************/ //utiliser le namespace System using System ; /** * objet qui contient notre fonction main */ class SecondProgramme { /** * méthode principale du programme */ public static void Main() { Console.Out.WriteLine("Nous n'avons pas encore créé de chien"); //création d'un objet chien new Chien(); Console.Out.WriteLine("un nouveau Chien est créé !"); } } /** * classe qui permet la création d'un objet de type Chien */ class Chien { /** * constructeur de notre classe chien */ Chien() { //la méthode ne fait rien pour l'instant } } |
Si nous compilons le programme à ce stade le compilateur va générer une erreur nous indiquant que le constructeur de la classe Chien est inaccessible. |
|
En
effet, tout comme la méthode Main, le constructeur Chien
doit être déclaré en public afin de pouvoir
être utilisé par d'autres objets. Pour mieux
comprendre ce principe, nous pouvons imaginer notre classe comme
un boîte noire qu'il est impossible d'ouvrir. Le terme
public nous permet de rendre visible certaines fonctionnalités
de cet objet et de les utiliser. A l'inverse private les rend
invisibles. |
public Chien() { //la méthode ne fait rien pour l'instant } |
La compilation et l'exécution de notre programme se fait maintenant sans aucun problème. |
|
Que fait ici notre programme ? Il crée une instance de la classe Chien par l'instruction : |
new Chien(); |
Lorsque
cette ligne est exécutée, C# cherche la classe
Chien. il regarde alors si elle contient un constructeur. Dans ce
cas celui-ci est exécuté et une instance de Chien
est créée. C# alloue alors de la mémoire à
cet objet, pour sa future utilisation par le programme, et le
place à un endroit que lui seul connaît. |
/** * constructeur de notre classe chien */ public Chien() { Console.Out.WriteLine("Ouah ! ouah !"); } |
Nous obtenons la sortie : |
|
nous
indiquant que le constructeur a été appelé et
donc qu'une instance de Chien a été créée. |
|
S'il
nous est possible de créer un objet facilement grâce
à l'opérateur new, il est en revanche impossible
d'utiliser cet objet dans le programme car nous ne savons pas où
il est placé en mémoire. |
|
codeur
C++ : On peut comparer le système de handle du C# aux
pointeurs du C++. Il est ainsi courant de dire qu'un handle pointe
sur un objet en mémoire. Nous reviendrons plus précisément
sur cette comparaison plus tard. |
Pour déclarer un handle, nous avons juste à indiquer le type de l'objet pointé par le handle (c'est à dire le nom de la classe), suivi par le nom que nous donnons à l'objet. Par exemple si nous voulons créer un handle sur une objet de type Chien que nous allons nommer pepette, nous ferons : |
Chien pepette; |
à l'intérieur de la classe qui gère notre programme (soit SecondProgramme). A ce stade le handle pepette ne pointe sur rien. On pourrait dire qu'il pointe sur null. Nous avons déclaré le handle mais nous ne l'avons pas initialisé. |
Pour
faire pointer un handle sur un objet nouvellement créé
à l'aide de l'opérateur new, nous allons utiliser le
signe égal "=". Ce signe, dans ce cas, doit être
lu comme "pointe sur". |
Chien Pepette; new Chien(); |
il n'y a aucun lien entre notre handle de la première ligne et l'objet venant d'être créé sur la seconde. Nous perdons donc notre objet dans la mémoire et restons avec une poignée ne s'agrippant à rien. Par contre avec le code suivant : |
Chien Pepette; pepette = new Chien(); |
pepette va pointer sur la nouvelle instance de la classe Chien que nous venons de créer. L'instruction : |
Chien Pepette; pepette = new Chien(); |
peut-être
lue comme : "pepette pointe sur la nouvelle instance de la
classe Chien". L'handle pepette va maintenant nous permettre
de manipuler l'objet. |
Chien Pepette = new Chien(); |
Changez maintenant le programme ainsi : |
//SecondProgramme.cs /**************************************************/ /* */ /* second programme d'apprentissage du C# */ /* (troisième version) */ /* Valentin BILLOTTE - " Le langage C # " 2001 */ /* */ /**************************************************/ //utiliser le namespace System using System ; /** * objet qui contient notre fonction Main */ class SecondProgramme { /** * méthode principale du programme */ public static void Main() { Console.Out.WriteLine("Nous n'avons pas encore créé de chien"); //création d'un objet chien Chien pepette = new Chien(); Console.Out.WriteLine("un nouveau Chien est créé !"); } } /** * classe qui permet la création d'un objet de type Chien */ class Chien { /** * constructeur de notre classe chien */ public Chien() { Console.Out.WriteLine("Ouah ! ouah !"); } } |
Si
vous le compilez et l'exécutez, vous obtiendrez la même
sortie qu'avec notre version sans handle, mais nous savons
maintenant que notre programme garde une trace du chien créé. |
/** * méthode principale du programme */ public static void Main() { Console.Out.WriteLine("Nous n'avons pas encore créé de chien"); //création d'un objet chien Chien pepette = new Chien(); Chien brutus = new Chien(); Chien rex = new Chien(); Console.Out.WriteLine("plusieurs objets de type Chien ont été créés !"); } |
nous donnant la sortie : |
|
Si nous avons de quoi manipuler nos objets désormais, notre classe Chien ne contient aucun membre (mis à part le constructeur) et ne peut donc faire aucune action. Nous allons donc rajouter une méthode à notre classe que nous nommerons Aboyer() qui va permettre aux instances de Chien de pouvoir émettre des sons après leur création. |
/** * classe qui permet la création d'un objet de type Chien */ class Chien { /** * constructeur de notre classe chien */ public Chien() { Console.Out.WriteLine("création d'un chien"); } /** * méthode qui permet à notre chien d'aboyer */ public void Aboyer() { Console.Out.WriteLine("Ouah ! ouah ! grrrrrrrrrrrrrrrr Ouah !"); } } |
Notre nouvelle classe indiquera à chaque nouvelle création d'une instance qu'un chien à été créé grâce à l'instruction |
Console.Out.WriteLine("un chien a été créé"); |
située l'intérieur du constructeur. Nous avons de même rajouté la méthode Aboyer() qui ne renvoie rien, comme l'indique le mot clé void la précédant, et n'accepte aucun paramètre (aucune données entre les parenthèses). Nous rajoutons enfin le terme public, afin de permettre d'utiliser la méthode depuis l'extérieur de l'objet. Celle-ci se contente d'afficher les cris d'un chien sur la sortie standard. |
/** * méthode qui permet à notre chien d'aboyer */ public void Aboyer() { Console.Out.WriteLine("Ouah ! ouah ! grrrrrrrrrrrrrrrr Ouah !"); } |
Grâce au handle sur pepette, nous allons pouvoir faire aboyer le chien à volonté. Pour faire référence à un membre d'un objet en C#, il suffit d'indiquer le handle de cet objet, suivi du nom du membre à utiliser, en les séparant à l'aide d'un point. Ainsi pour faire aboyer pepette, nous ferons : |
pepette.Aboyer(); |
à l'intérieur de notre méthode Main : |
/** * méthode principale du programme */ public static void Main() { Console.Out.WriteLine("Nous n'avons pas encore créé de chien"); //création d'un objet chien Chien pepette = new Chien(); //Console.Out.WriteLine("un nouveau Chien est créé !"); pepette.Aboyer(); } |
nous donnant la sortie : |
|
En poussant notre expérience un peu plus loin, nous pourrions créer une histoire avec deux chiens que nous nommerions brutus et pepette. Nous allons les faire vivre quelques secondes. Il faut pour cela permettre aux chiens de sentir et de couiner grâce aux méthodes Sentir() et Couiner() rajoutées à la classe Chien. Nous allons évidemment créer deux handles portant le nom de nos deux chiens dans notre méthode Main(). |
//SecondProgramme.cs /**************************************************/ /* */ /* second programme d'apprentissage du C# */ /* (dernière version) */ /* Valentin BILLOTTE - " Le langage C # " 2001 */ /* */ /**************************************************/ //utiliser le namespace System using System ; /** * objet qui contient notre fonction main */ class SecondProgramme : object { /** * méthode principale du programme */ public static void Main() { Chien pepette; Chien brutus; //créer nos chiens Console.Out.WriteLine("création du chien brutus dans notre univers"); brutus = new Chien(); Console.Out.WriteLine("création du chien pepette dans notre univers"); pepette = new Chien(); //raconter l'histoire Console.Out.WriteLine("brutus et pepette se rencontrent..."); Console.Out.WriteLine("brutus sent pepette..."); brutus.Sentir(); Console.Out.WriteLine("et pepette sent brutus"); pepette.Sentir(); Console.Out.WriteLine("brutus s'énerve et aboie !"); brutus.Aboyer(); Console.Out.WriteLine("pepette se sauve..."); pepette.Couiner(); Console.Out.WriteLine("notre histoire est terminée..."); } } /** * classe qui permet la création d'un objet de type Chien */ class Chien : object { /** * constructeur de notre classe chien */ public Chien() { Console.Out.WriteLine("création d'un chien"); } /** * méthode qui permet à notre chien d'aboyer */ public void Aboyer() { Console.Out.WriteLine("Ouah ! ouah ! grrrrrrrrrrrrrrrr Ouah !"); } /** * méthode qui permet à notre chien de couiner */ public void Couiner() { Console.Out.WriteLine("Kaï Kaï Kaï !!!!"); } /** * méthode qui permet à notre chien de sentir */ public void Sentir() { Console.Out.WriteLine("snif ? snif ! snif ?!"); } } |
Comme
nous le voyons ici, grâce aux handles nous pouvons manipuler
nos objets comme nous le voulons. |
pepette = null; |
|
Dans
certains langages, les programmeurs doivent continuellement se
préoccuper de libérer la mémoire des
différents objets qu'ils ont créés. |