Classe Personne en Programmation Orientée Objet
Classe Personne en Programmation Orientée Objet
using System;
using [Link];
using [Link];
using [Link];
namespace Chapitre6
{
class Personne
{
// attributs
private string prenom;
private string nom;
private int age;
// méthode
public void Initialise(string P, string N, int age)
{
[Link] = P;
[Link] = N;
[Link] = age;
}
// méthode
public void Identifie()
{
[Link]("[{0}, {1}, {2}]", prenom, nom, age);
}
}
Les attributs peuvent être accompagnés de l'un des trois mots clés suivants :
privé : Un champ privé (private) n'est accessible que par les seules méthodes internes
de la classe
public : Un champ public (public) est accessible par toute méthode définie ou non au
sein de la classe
protégé : Un champ protégé (protected) n'est accessible que par les seules méthodes
internes de la classe ou d'un objet dérivé.
30
Chapitre 6 : Programmation orientée objet
Parce que nom, prenom et age sont des données privées de la classe Personne, les
instructions :
Personne p1;
[Link] = "Mohamed";
[Link] = "Salah";
[Link] = 30;
sont illégales.
Il nous faut initialiser un objet de type Personne via une méthode publique. C'est le
rôle de la méthode Initialise. On écrira :
Personne p1;
[Link]("Mohamed", "Salah", 30);
La séquence d'instructions
Personne p1;
[Link]("Mohamed", "Salah", 30);
est incorrecte.
L'instruction Personne p1; déclare p1 comme une référence à un objet de type Personne.
Cet objet n'existe pas encore et donc p1 n'est pas initialisé.
Cela a pour effet de créer un objet de type Personne non encore initialisé : les attributs
nom et prenom qui sont des références d'objets de type String auront la valeur null, et age la
valeur 0. Il y a donc une initialisation par défaut. Maintenant que p1 référence un objet,
l'instruction d'initialisation de cet objet [Link]("Mohamed","Salah",30); est valide.
31
Chapitre 6 : Programmation orientée objet
Voici un court programme de test. Celui-ci est écrit dans le fichier source
[[Link]] :
using System;
using [Link];
using [Link];
using [Link];
namespace Chapitre6
{
class Program
{
static void Main(string[] args)
{
Personne p1 = new Personne();
[Link]("Mohamed", "Salah", 30);
[Link]();
}
}
}
On a maintenant deux méthodes portant le nom Initialise : c'est légal tant qu'elles
admettent des paramètres différents. C'est le cas ici. Le paramètre est maintenant une
référence p à une personne. Les attributs de la personne p sont alors affectés à l'objet courant
(this). On remarquera que la méthode Initialise a un accès direct aux attributs de l'objet p bien
que ceux-ci soient de type private. C'est toujours vrai : un objet o d'une classe C a toujours
accès aux attributs des objets de la même classe C.
namespace Chapitre6
{
class Program
{
static void Main(string[] args)
{
Personne p1 = new Personne();
[Link]("Mohamed", "Salah", 30);
[Link]();
Personne p2 = new Personne();
[Link](p1);
[Link]();
32
Chapitre 6 : Programmation orientée objet
}
}
}
et ses résultats :
[Mohamed, Salah, 30]
[Mohamed, Salah, 30]
Un constructeur est une méthode qui porte le nom de la classe et qui est appelée lors
de la création de l'objet. On s'en sert généralement pour l'initialiser. C'est une méthode qui
peut accepter des arguments mais qui ne rend aucun résultat. Son prototype ou sa définition
ne sont précédés d'aucun type (pas même void).
Si une classe C a un constructeur acceptant n arguments argi, la déclaration et l'initialisation
d'un objet de cette classe pourra se faire sous la forme :
C objet =new C(arg1,arg2, ... argn);
ou
C objet;
…
objet=new C(arg1,arg2, ... argn);
Si une classe C n'a aucun constructeur, elle en a un par défaut qui est le constructeur
sans paramètres : public C(). Les attributs de l'objet sont alors initialisés avec des valeurs par
défaut. C'est ce qui s'est passé lorsque dans les programmes précédents, où on avait écrit :
Personne p1;
p1 = new Personne();
namespace Chapitre6
{
class Personne
{
// attributs
private string prenom;
private string nom;
private int age;
// constructeurs
public Personne(String p, String n, int age)
{
Initialise(p, n, age);
}
public Personne(Personne P)
{
Initialise(P);
}
33
Chapitre 6 : Programmation orientée objet
[Link] = age;
}
public void Identifie()
{
[Link]("[{0}, {1}, {2}]", prenom, nom, age);
}
public void Initialise(Personne p)
{
prenom = [Link];
nom = [Link];
age = [Link];
}
}
}
Nos deux constructeurs se contentent de faire appel aux méthodes Initialise étudiées
précédemment. On rappelle que lorsque dans un constructeur, on trouve la notation
Initialise(p) par exemple, le compilateur traduit par [Link](p). Dans le constructeur, la
méthode Initialise est donc appelée pour travailler sur l'objet référencé par this, c'est à dire
l'objet courant, celui qui est en cours de construction.
Voici un court programme de test :
using System;
namespace Chapitre6
{
class Program
{
static void Main(string[] args)
{
Personne p1 = new Personne("Mohamed", "Salah", 30);
[Link]();
Personne p2 = new Personne(p1);
[Link]();
}
}
}
Dans une expression, on peut faire appel explicitement au constructeur d'un objet :
celui-ci est construit, mais nous n'y avons pas accès (pour le modifier par exemple). Cet objet
temporaire est construit pour les besoins d'évaluation de l'expression puis abandonné.
L'espace mémoire qu'il occupait sera automatiquement récupéré ultérieurement par un
programme appelé "ramassemiettes" dont le rôle est de récupérer l'espace mémoire occupé
par des objets qui ne sont plus référencés par des données du programme.
namespace Chapitre6
{
class Program
34
Chapitre 6 : Programmation orientée objet
{
static void Main(string[] args)
{
new Personne(new Personne("Mohamed", "Salah", 30)).Identifie();
}
}
}
et modifions les constructeurs de la classe Personne afin qu'ils affichent un message :
// constructeurs
public Personne(String p, String n, int age)
{
[Link]("Constructeur Personne(string, string, int)");
Initialise(p, n, age);
}
public Personne(Personne P)
{
[Link]("Constructeur Personne(Personne)");
Initialise(P);
}
Nous obtenons les résultats suivants :
Constructeur Personne(string, string, int)
Constructeur Personne(Personne)
[Mohamed, Salah, 30]
montrant la construction successive des deux objets temporaires.
Nous rajoutons à la classe Personne les méthodes nécessaires pour lire ou modifier
l'état des attributs des objets :
using System;
namespace Chapitre6
{
class Personne
{
// attributs
private string prenom;
private string nom;
private int age;
// constructeurs
public Personne(String p, String n, int age)
{
[Link]("Constructeur Personne(string, string,
int)");
Initialise(p, n, age);
}
public Personne(Personne p)
{
[Link]("Constructeur Personne(Personne)");
Initialise(p);
}
// méthode
public void Initialise(string p, string n, int age)
{
[Link] = p;
[Link] = n;
[Link] = age;
35
Chapitre 6 : Programmation orientée objet
}
public void Initialise(Personne p)
{
prenom = [Link];
nom = [Link];
age = [Link];
}
// accesseurs
public String GetPrenom()
{
return prenom;
}
public String GetNom()
{
return nom;
}
public int GetAge()
{
return age;
}
//modifieurs
public void SetPrenom(String P)
{
[Link] = P;
}
public void SetNom(String N)
{
[Link] = N;
}
public void SetAge(int age)
{
[Link] = age;
}
// méthode
public void Identifie()
{
[Link]("[{0}, {1}, {2}]", prenom, nom, age);
}
}
}
namespace Chapitre6
{
class Program
{
static void Main(string[] args)
{
Personne p = new Personne("Mohamed", "Mustapha", 34);
[Link]("p=(" + [Link]() + "," + [Link]()
+ "," + [Link]() + ")");
[Link](56);
[Link]("p=(" + [Link]() + "," + [Link]()
+ "," + [Link]() + ")");
}
}
}
et nous obtenons les résultats :
Constructeur Personne(string, string, int)
36
Chapitre 6 : Programmation orientée objet
p=(Mohamed,Mustapha,34)
p=(Mohamed,Mustapha,56)
Il existe une autre façon d'avoir accès aux attributs d'une classe, c'est de créer des
propriétés. Celles-ci nous permettent de manipuler des attributs privés comme s'ils étaient
publics.
Considérons la classe Personne suivante où les accesseurs et modifieurs précédents
ont été remplacés par des propriétés en lecture et écriture :
using System;
namespace Chapitre6
{
class Personne
{ // attributs
private string prenom;
private string nom;
private int age;
// constructeurs
public Personne(String p, String n, int age)
{
Initialise(p, n, age);
}
public Personne(Personne p)
{
Initialise(p);
}
// méthode
public void Initialise(string p, string n, int age)
{
[Link] = p;
[Link] = n;
[Link] = age;
}
public void Initialise(Personne p)
{
prenom = [Link];
nom = [Link];
age = [Link];
}
// propriétés
public string Prenom
{
get { return prenom; }
set
{
// prénom valide ?
if (value == null || [Link]().Length == 0)
{
throw new Exception("prénom (" + value + ") invalide");
}
else
{
prenom = value;
}
}//if
}//prenom
37
Chapitre 6 : Programmation orientée objet
Elle peut en profiter pour faire des vérifications sur la validité de la valeur reçue et
éventuellement lancer une exception si la valeur se révèle invalide. C'est ce qui est fait ici.
Comment ces méthodes get et set sont-elles appelées ? Considérons le programme de test
suivant :
using System;
namespace Chapitre6
38
Chapitre 6 : Programmation orientée objet
{
class Program
{
static void Main(string[] args)
{
Personne p = new Personne("Mohamed", "Salah", 34);
[Link]("p=(" + [Link] + "," + [Link] + "," +
[Link] + ")");
[Link] = 56;
[Link]("p=(" + [Link] + "," + [Link] + "," +
[Link] + ")");
try
{
[Link] = -4;
}
catch (Exception ex)
{
[Link]([Link]);
}//try-catch
}
}
}
Dans l'instruction [Link]=56; on veut fixer la valeur de la propriété Age. C'est alors la
méthode set de cette propriété qui est alors appelée. Elle recevra 56 dans son paramètre value.
Une propriété P d'une classe C qui ne définirait que la méthode get est dite en lecture
seule. Si c est un objet de classe C, l'opération c.P=valeur sera alors refusée par le
compilateur.
Supposons qu'on veuille compter le nombre d'objets Personne créées dans une
application. On peut soi-même gérer un compteur mais on risque d'oublier les objets
temporaires qui sont créés ici ou là.
Il semblerait plus sûr d'inclure dans les constructeurs de la classe Personne, une
instruction incrémentant un compteur. Le problème est de passer une référence de ce
compteur afin que le constructeur puisse l'incrémenter : il faut leur passer un nouveau
paramètre.
39
Chapitre 6 : Programmation orientée objet
namespace Chapitre6
{
public class Personne
{ // attributs de classe
private static long nbPersonnes;
public static long NbPersonnes
{
get { return nbPersonnes; }
}
// attributs d'instance
private string prenom;
private string nom;
private int age;
// constructeurs
public Personne(String p, String n, int age)
{
Initialise(p, n, age);
nbPersonnes++;
}
public Personne(Personne p)
{
Initialise(p);
nbPersonnes++;
}
// méthode
public void Initialise(string p, string n, int age)
{
[Link] = p;
[Link] = n;
[Link] = age;
}
public void Initialise(Personne p)
{
prenom = [Link];
nom = [Link];
age = [Link];
}
…
}
}
40
Chapitre 6 : Programmation orientée objet
using System;
namespace Chapitre6
{
class Program
{
static void Main(string[] args)
{
Personne p1 = new Personne("Mohamed", "Salah", 30);
Personne p2 = new Personne(p1);
new Personne(p1);
[Link]("Nombre de personnes créées : " +
[Link]);
}
}
}
on obtient les résultats suivants :
Nombre de personnes créées : 3
Un objet est une donnée comme une autre et à ce titre plusieurs objets peuvent être
rassemblés dans un tableau :
using System;
namespace Chapitre6
{
class Program
{
static void Main(string[] args)
{
// un tableau de personnes
Personne[] amis = new Personne[3];
amis[0] = new Personne("Mohamed", "Salah", 30);
amis[1] = new Personne("Slim", "Ben Slim", 52);
amis[2] = new Personne("Neil", "Armstrong", 66);
// affichage
foreach (Personne ami in amis)
{
[Link]();
}
}
}
}
On obtient les résultats suivants :
[Mohamed, Salah, 30]
[Slim, Ben Slim, 52]
[Neil, Armstrong, 66]
41
Chapitre 6 : Programmation orientée objet
Sort une méthode générique où T désigne un type quelconque. La méthode reçoit deux
paramètres :
- T[] tableau : le tableau d'éléments de type T à trier
- IComparer<T> comparateur : une référence d'objet implémentant l'interface IComparer<T>.
Par exemple, si p1 et p2 sont deux objets Personne, on pourra dire que p1>p2 si le nom de
p1 précède le nom de p2 dans l'ordre alphabétique. On aura alors un tri croissant selon le nom
des personnes. Si on veut un tri selon l'âge, on dira que p1>p2 si l'âge de p1 est supérieur à
l'âge de p2.
- pour avoir un tri dans l'ordre décroissant, il suffit d'inverser les résultats +1 et -1
Exemple :
using System;
using [Link] ;
namespace Chapitre6
{
class Program
{
static void Main(string[] args)
{
// un tableau de personnes
Personne[] personnes1 = { new Personne("Ben Saleh", "Taoufik",
25), new Personne("Troudi","Samir", 35), new
Personne("Mustafa", "Samir", 32) };
// affichage
Affiche("Tableau a trier ", personnes1);
// tri selon le nom
[Link](personnes1, new CompareNoms());
// affichage
Affiche("Tableau apres le tri selon les nom et prenom ",
personnes1);
// tri selon l'âge
[Link](personnes1, new CompareAges());
// affichage
Affiche("Tableau apres le tri selon l'age ", personnes1);
}
42
Chapitre 6 : Programmation orientée objet
Tableau à trier-----------------------------------
[Ben Saleh, Taoufik, 25]
[Troudi, Samir, 35]
[Mustafa, Samir, 32]
6.2.1 Généralités
Le but de l'héritage est de "personnaliser" une classe existante pour qu'elle satisfasse à
nos besoins.
43
Chapitre 6 : Programmation orientée objet
Supposons qu'on veuille créer une classe Enseignant : un enseignant est une personne
particulière. Il a des attributs qu'une autre personne n'aura pas : la matière qu'il enseigne par
exemple. Mais il a aussi les attributs de toute personne : prénom, nom et âge.
Un enseignant fait donc pleinement partie de la classe Personne mais a des attributs
supplémentaires.
Plutôt que d'écrire une classe Enseignant à partir de rien, on préfèrerait reprendre
l'acquis de la classe Personne qu'on adapterait au caractère particulier des enseignants. C'est
le concept.
Pour exprimer que la classe Enseignant hérite des propriétés de la classe Personne, on écrira :
public class Enseignant : Personne
Personne est appelée la classe parent (ou mère) et Enseignant la classe dérivée (ou fille).
Un objet Enseignant a toutes les qualités d'un objet Personne : il a les mêmes attributs
et les mêmes méthodes. Ces attributs et méthodes de la classe parent ne sont pas répétées dans
la définition de la classe fille : on se contente d'indiquer les attributs et méthodes rajoutés par
la classe fille :
Nous supposons que la classe Personne est définie comme suit :
using System;
namespace Chapitre6
{
public class Personne
{ // attributs de classe
private static long nbPersonnes;
public static long NbPersonnes
{
get { return nbPersonnes; }
}
// attributs d'instance
private string prenom;
private string nom;
private int age;
// constructeurs
public Personne(String prenom, String nom, int age)
{
Nom = nom;
Prenom = prenom;
Age = age;
nbPersonnes++;
[Link]("Constructeur Personne(string, string,
int)");
}
public Personne(Personne p)
{
Nom = [Link];
Prenom = [Link];
Age = [Link];
nbPersonnes++;
[Link]("Constructeur Personne(Personne)");
}
// propriétés
public string Prenom
44
Chapitre 6 : Programmation orientée objet
{
get { return prenom; }
set
{
// prénom valide ?
if (value == null || [Link]().Length == 0)
{
throw new Exception("prénom (" + value + ") invalide");
}
else
{
prenom = value;
}
}//if
}//prenom
namespace Chapitre6
{
class Enseignant : Personne
{
45
Chapitre 6 : Programmation orientée objet
// attributs
private int section;
// constructeur
public Enseignant(string prenom, string nom, int age, int section)
: base(prenom, nom, age)
{
// on mémorise la section via la propriété Section
Section = section;
// suivi
[Link]("Construction Enseignant(string, string, int,
int)");
}//constructeur
// propriété Section
public int Section
{
get { return section; }
set { section = value; }
}// Section
}
}
Tentons un premier programme de test [[Link]] :
using System;
namespace Chapitre6
{
class Program
{
static void Main(string[] args)
{
[Link](new Enseignant("Mohamed", "Salah", 30, 27).Identite);
}
}
}
Ce programme ce contente de créer un objet Enseignant (new) et de l'identifier. La
classe Enseignant n'a pas de méthode Identite mais sa classe parent en a une qui de plus est
publique : elle devient par héritage une méthode publique de la classe Enseignant.
Les résultats obtenus sont les suivants :
Constructeur Personne(string, string, int)
Construction Enseignant(string, string, int, int)
[Mohamed, Salah, 30]
1. using System;
2. namespace Chapitre6{
3. class Enseignant : Personne
4. {
5. // attributs
6. private int section;
7. // constructeur
46
Chapitre 6 : Programmation orientée objet
Ligne 24-26 : La propriété Identite de la classe Enseignant s'appuie sur la propriété Identite
de sa classe mère ([Link]) (ligne 25) pour afficher sa partie "Personne" puis complète
avec le champ section qui est propre à la classe Enseignant. Notons la déclaration de la
propriété Identite :
public new string Identite{
La propriété Identite est définie à la fois dans la classe Enseignant et sa classe mère
Personne. Dans la classe fille Enseignant, la propriété Identite doit être précédée du mot clé
new pour indiquer qu'on redéfinit une nouvelle propriété Identite pour la classe Enseignant.
public new string Identite{
47
Chapitre 6 : Programmation orientée objet
6.2.3 Le polymorphisme
Le fait qu'une variable Oi de classe Ci puisse en fait référencer non seulement un objet
de la classe Ci mais en fait tout objet dérivé de la classe Ci, est appelé polymorphisme : la
faculté pour une variable de référencer différents types d'objets.
Prenons un exemple et considérons la fonction suivante indépendante de toute classe (static):
public static void Affiche(Personne p){
….
}
On pourra aussi bien écrire
Personne p;
...
Affiche(p);
que
Enseignant e;
...
Affiche(e);
Dans ce dernier cas, le paramètre formel p de type Personne de la méthode statique
Affiche va recevoir une valeur de type Enseignant. Comme le type Enseignant dérive du type
Personne, c'est légal.
1. using System;
2. namespace Chapitre6 {
3. class Program {
4. static void Main(string[] args){
5. // un enseignant
6. Enseignant e = new Enseignant("Mounir", "Jendoubi", 56, 61);
7. Affiche(e);
8. // une personne
9. Personne p = new Personne("Mohamed", "Salah", 30);
10. Affiche(p);
11. }
12. // affiche
13. public static void Affiche(Personne p) {
14. // affiche identité de p
15. [Link]([Link]);
48
Chapitre 6 : Programmation orientée objet
16. }//affiche
17. }
18. }
L'exécution montre que l'instruction [Link] (ligne 15) a exécuté à chaque fois la
propriété Identite d'une Personne, d'abord (ligne 6) la personne contenue dans l'Enseignant e,
puis (ligne 9) la Personne p elle-même. Elle ne s'est pas adaptée à l'objet réellement passé en
paramètre à Affiche.
On aurait préféré avoir l'identité complète de l'Enseignant e. Il aurait fallu pour cela
que la notation [Link] référence la propriété Identite de l'objet réellement pointé par p
plutôt que la propriété Identite de partie "Personne" de l'objet réellement par p.
Il est possible d'obtenir ce résultat en déclarant Identite comme une propriété virtuelle
(virtual) dans la classe de base Personne :
Le mot clé virtual fait de Identite une propriété virtuelle. Ce mot clé peut s'appliquer
également aux méthodes. Les classes filles qui redéfinissent une propriété ou méthode
virtuelle doivent alors utiliser le mot clé override au lieu de new pour qualifier leur
propriété/méthode redéfinie. Ainsi dans la classe Enseignant, la propriété Identite est redéfinie
comme suit :
public override string Identite
{
get {return [Link]("Enseignant[{0},{1}]", [Link], Section);}
}
La classe object (alias C# de [Link]) est la classe "mère" de toutes les classes C#.
Ainsi lorsqu'on écrit :
public class Personne
on écrit implicitement :
public class Personne : [Link]
La classe [Link] définit une méthode virtuelle ToString :
49
Chapitre 6 : Programmation orientée objet
namespace Chapitre6
{
class Program
{
static void Main(string[] args)
{
// un enseignant
[Link](new Enseignant("Mounir", "Jendoubi", 56, 61).ToString());
// une personne
[Link](new Personne("Mohamed", "Salah", 30).ToString());
}
}
}
On remarquera que bien que nous n'ayons pas redéfini la méthode ToString dans les
classes Personne et Enseignant, on peut cependant constater que la méthode ToString de la
classe Object a été capable d'afficher le nom réel de la classe de l'objet.
La définition est la même dans les deux classes. Considérons le programme de test suivant :
1. using System;
2. namespace Chapitre6
3. {
4. class Program
5. {
6. static void Main(string[] args)
7. {
8. Enseignant e = new Enseignant("Mounir", "Jendoubi", 56, 61);
9. Affiche(e);
10. // une personne
11. Personne p = new Personne("Mohamed", "Salah", 30);
12. Affiche(p);
13. }
14. // affiche
15. public static void Affiche(Personne p)
16. {
17. // affiche identité de p
18. [Link](p);
19. }//Affiche
}
50
Chapitre 6 : Programmation orientée objet
Attardons-nous sur la méthode Affiche qui admet pour paramètre une personne p.
Ligne 18, la méthode WriteLine de la classe Console n'a aucune variante admettant un
paramètre de type Personne.
Parmi les différentes variantes de Writeline, il en existe une qui admet comme
paramètre un type Object.
Le compilateur va utiliser cette méthode, WriteLine(Object o), parce que cette
signature signifie que le paramètre o peut être de type Object ou dérivé. Puisque Object est la
classe mère de toutes les classes, tout objet peut être passé en paramètre à WriteLine et donc
un objet de type Personne ou Enseignant. La méthode WriteLine(Object o) écrit [Link]()
dans le flux d'écriture Out.
La méthode ToString étant virtuelle, si l'objet o (de type Object ou dérivé) a redéfini la
méthode ToString, ce sera cette dernière qui sera utilisée. C'est ici le cas avec les classes
Personne et Enseignant.
C'est ce que montrent les résultats d'exécution :
Constructeur Personne(string, string, int)
Construction Enseignant(string, string, int, int)
Enseignant[[Mounir, Jendoubi, 56],61]
Constructeur Personne(string, string, int)
[Mohamed, Salah, 30]
Exemple
On crée une classe ListeDePersonnes dérivée de la classe ArrayList. Cette classe implémente
une liste dynamique.. De cette classe, nous n'utilisons que les éléments suivants :
- la méthode [Link](Object o) permettant d'ajouter à la liste L un objet o. Ici l'objet o
sera un objet Personne.
- la propriété [Link] qui donne le nombre d'éléments de la liste L
- la notation L[i] qui donne l'élément i de la liste L
51
Chapitre 6 : Programmation orientée objet
using System;
using [Link];
using [Link];
namespace Chapitre6
{
class ListeDePersonnes : ArrayList
{
// redéfinition opérateur +, pour ajouter une personne à la liste
public static ListeDePersonnes operator +(ListeDePersonnes l,
Personne p)
{
// on ajoute la Personne p à la ListeDePersonnes l
[Link](p);
// on rend la ListeDePersonnes l
return l;
}// operator +
// ToString
public override string ToString()
{
// rend (él1, él2, ..., éln)
// parenthèse ouvrante
StringBuilder listeToString = new StringBuilder("(");
// on parcourt la liste de personnes (this)
for (int i = 0; i < Count - 1; i++)
{
[Link](this[i]).Append(",");
}//for
// dernier élément
if (Count != 0)
{
[Link](this[Count - 1]);
}
// parenthèse fermante
[Link](")");
// on doit rendre un string
return [Link]();
}//ToString
}
}
namespace Chapitre6
{
class Program
{
static void Main(string[] args)
{
// une liste de personnes
ListeDePersonnes l = new ListeDePersonnes();
// ajout de personnes
52
Chapitre 6 : Programmation orientée objet
53