• Aucun résultat trouvé

2 Classes, Stuctures, Interfaces

2.5 Les structures

La structure C# est analogue à la structure du langage C et est très proche de la notion de classe. Une structure est définie comme suit : struct NomStructure{ // attributs ... // propriétés ... // constructeurs ... // méthodes ... }

Il y a, malgré une similitude de déclaration des différences importantes entre classe et structure. La notion d'héritage n'existe par exemple pas avec les structures. Si on écrit une classe qui ne doit pas être dérivée, quelles sont les différences entre structure et

classe qui vont nous aider à choisir entre les deux ? Aidons-nous de l'exemple suivant pour le découvrir :

1. using System; 2.

3. namespace Chap2 { 4. class Program1 {

5. static void Main(string[] args) { 6. // une structure sp1

7. SPersonne sp1;

8. sp1.Nom = "paul"; 9. sp1.Age = 10;

10. Console.WriteLine("sp1=SPersonne(" + sp1.Nom + "," + sp1.Age + ")"); 11. // une structure sp2

12. SPersonne sp2 = sp1;

13. Console.WriteLine("sp2=SPersonne(" + sp2.Nom + "," + sp2.Age + ")"); 14. // sp2 est modifié

16. sp2.Age = 30;

17. // vérification sp1 et sp2

18. Console.WriteLine("sp1=SPersonne(" + sp1.Nom + "," + sp1.Age + ")"); 19. Console.WriteLine("sp2=SPersonne(" + sp2.Nom + "," + sp2.Age + ")"); 20.

21. // un objet op1

22. CPersonne op1=new CPersonne();

23. op1.Nom = "paul"; 24. op1.Age = 10;

25. Console.WriteLine("op1=CPersonne(" + op1.Nom + "," + op1.Age + ")"); 26. // un objet op2

27. CPersonne op2=op1;

28. Console.WriteLine("op2=CPersonne(" + op2.Nom + "," + op2.Age + ")"); 29. // op2 est modifié

30. op2.Nom = "nicole"; 31. op2.Age = 30;

32. // vérification op1 et op2

33. Console.WriteLine("op1=CPersonne(" + op1.Nom + "," + op1.Age + ")"); 34. Console.WriteLine("op2=CPersonne(" + op2.Nom + "," + op2.Age + ")");

35. }

36. }

37. // structure SPersonne 38. struct SPersonne { 39. public string Nom; 40. public int Age; 41. }

42.

43. // classe CPersonne 44. class CPersonne { 45. public string Nom; 46. public int Age; 47. }

48. 49. }

lignes 38-41 : une structure avec deux champs publics : Nom, Agelignes 44-47 : une classe avec deux champs publics : Nom, Age Si on exécute ce programme, on obtient les résultats suivants :

1. sp1=SPersonne(paul,10) 2. sp2=SPersonne(paul,10) 3. sp1=SPersonne(paul,10) 4. sp2=SPersonne(nicole,30) 5. op1=CPersonne(paul,10) 6. op2=CPersonne(paul,10) 7. op1=CPersonne(nicole,30) 8. op2=CPersonne(nicole,30)

Là où précédemment on utilisait une classe Personne, nous utilisons maintenant une structure SPersonne : 1. struct SPersonne {

2. public string Nom; 3. public int Age; 4. }

La structure n'a ici pas de constructeur. Elle pourrait en avoir un comme nous le montrerons plus loin. Par défaut, elle dispose toujours du constructeur sans paramètres, ici SPersonne().

• ligne 7 du code : la déclaration SPersonne sp1; est équivalente à l'instruction :

SPersonne sp1=new Spersonne();

Une structure (Nom,Age) est créée et la valeur de sp1 est cette structure elle-même. Dans le cas de la classe, la création de l'objet (Nom,Age) doit se faire explicitement par l'opérateur new (ligne 22) :

L'instruction précédente crée un objet CPersonne (grosso modo l'équivalent de notre structure) et la valeur de p1 est alors

l'adresse (la référence) de cet objet.

Résumons

dans le cas de la structure, la valeur de sp1 est la structure elle-mêmedans le cas de la classe, la valeur de op1 est l'adresse de l'objet créé

Lorsque dans le programme on écrit ligne 12 : SPersonne sp2 = sp1;

une nouvelle structure sp2(Nom,Age) est créée et initialisée avec la valeur de sp1, donc la structure elle-même.

La structure de sp1 est dupliquée dans sp2 [1]. C'est une recopie de valeur. Considérons maintenant l'instruction, ligne 27 : CPersonne op2=op1;

Dans le cas des classes, la valeur de op1 est recopiée dans op2, mais comme cette valeur est en fait l'adresse de l'objet, celui-ci n'est pas dupliqué [2].

Dans le cas de la structure [1], si on modifie la valeur de sp2 on ne modifie pas la valeur de sp1, ce que montre le programme. Dans le cas de l'objet [2], si on modifie l'objet pointé par op2, celui pointé par op1 est modifié puisque c'est le même. C'est ce que montrent également les résultats du programme.

On retiendra donc de ces explications que :

 la valeur d'une variable de type structure est la structure elle-même  la valeur d'une variable de type objet est l'adresse de l'objet pointé

Une fois cette différence fondamentale comprise, la structure se montre très proche de la classe comme le montre le nouvel exemple suivant : 1. using System; 2. 3. namespace Chap2 { 4. 5. // structure SPersonne 6. struct SPersonne { 7. // attributs privés 8. private string nom; 9. private int age; 10.

11. // propriétés 12. public string Nom { 13. get { return nom; }

Structure p1 Objet p1 Nom Age Nom Age op1 sp1 sp1 paul 10 sp2 paul 10 op1 paul 10 op2 ---> ---> 1 2

14. set { nom = value; } 15. }//nom

16.

17. public int Age { 18. get { return age; } 19. set { age = value; } 20. }//age

21.

22. // Constructeur

23. public SPersonne(string nom, int age) { 24. this.nom = nom;

25. this.age = age; 26. }//constructeur 27.

28. // ToString

29. public override string ToString() {

30. return "SPersonne(" + Nom + "," + Age + ")"; 31. }//ToString

32. }//structure 33. }//namespace

• lignes 8-9 : deux champs privés

• lignes 12-20 : les propriétés publiques associées

lignes 23-26 : on définit un constructeur. A noter que le constructeur sans paramètres SPersonne() est toujours présent et n'a pas à être déclaré. Sa déclaration est refusée par le compilateur. Dans le constructeur des lignes 23-26, on pourrait être tenté d'initialiser les champs privés nom, age via leurs propriétés publiques Nom, Age. C'est refusé par le compilateur. Les méthodes de la structure ne peuvent être utilisées lors de la construction de celle-ci.

lignes 29-31 : redéfinition de la méthode ToString. Un programme de test pourrait être le suivant :

1. using System; 2.

3. namespace Chap2 { 4. class Program1 {

5. static void Main(string[] args) { 6. // une personne p1

7. SPersonne p1=new SPersonne();

8. p1.Nom="paul"; 9. p1.Age= 10; 10. Console.WriteLine("p1={0}",p1); 11. // une personne p2 12. SPersonne p2 = p1; 13. Console.WriteLine("p2=" + p2); 14. // p2 est modifié 15. p2.Nom = "nicole"; 16. p2.Age = 30; 17. // vérification p1 et p2 18. Console.WriteLine("p1=" + p1); 19. Console.WriteLine("p2=" + p2); 20. // une personne p3

21. SPersonne p3 = new SPersonne("amandin", 18); 22. Console.WriteLine("p3=" + p3);

23. // une personne p4

24. SPersonne p4 = new SPersonne { Nom = "x", Age = 10 }; 25. Console.WriteLine("p4=" + p4);

26. }

27. } 28. }

• ligne 7 : on est obligés d'utiliser explicitement le constructeur sans paramètres, ceci parce qu'il existe un autre constructeur dans la structure. Si la structure n'avait eu aucun constructeur, l'instruction

SPersonne p1;

aurait suffi pour créer une structure vide.

• lignes 8-9 : la structure est initialisée via ses propriétés publiques • ligne 10 : la méthode p1.ToString va être utilisée dans le WriteLine.ligne 21 : création d'une structure avec le constructeur SPersonne(string,int)

ligne 24 : création d'une structure avec le constructeur sans paramètres SPersonne() avec, entre accolades, initialisation des champs privés via leurs propriétés publiques.

On obtient les résultats d'exécution suivants : 1. p1=SPersonne(paul,10) 2. p2=SPersonne(paul,10) 3. p1=SPersonne(paul,10) 4. p2=SPersonne(nicole,30) 5. p3=SPersonne(amandin,18) 6. p4=SPersonne(x,10)

La seule différence notable ici entre structure et classe, c'est qu'avec une classe les objets p1 et p2 auraient pointé sur le même objet à la fin du programme.