'>

l'objet en C sharp: Méthodes de lecture et d'écriture des attributs privés + Les propriétés

2.1.13 Méthodes de lecture et d'écriture des attributs privés
Nous rajoutons à la classe Personne les méthodes nécessaires pour lire ou modifier l'état des attributs des objets :
1. using System;
2.
3. namespace Chap2 {
4. public class Personne {
5. // attributs
6. private string prenom;
7. private string nom;
8. private int age;
9.
10. // constructeurs
11. public Personne(String p, String n, int age) {
12. Console.WriteLine("Constructeur Personne(string, string, int)");
13. Initialise(p, n, age);
14. }
15. public Personne(Personne p) {
16. Console.Out.WriteLine("Constructeur Personne(Personne)");
17. Initialise(p);
18. }
19.
20. // méthode
21. public void Initialise(string p, string n, int age) {
22. this.prenom = p;
23. this.nom = n;
24. this.age = age;
25. }
26.
27. public void Initialise(Personne p) {
28. prenom = p.prenom;
29. nom = p.nom;
30. age = p.age;
31. }
32.
33. // accesseurs
34. public String GetPrenom() {
35. return prenom;
36. }
37. public String GetNom() {
38. return nom;
39. }
40. public int GetAge() {
41. return age;
42. }
43.
44. //modifieurs
45. public void SetPrenom(String P) {
46. this.prenom = P;
47. }
48. public void SetNom(String N) {
49. this.nom = N;
50. }
51. public void SetAge(int age) {
52. this.age = age;
53. }
54.
55. // méthode
56. public void Identifie() {
57. Console.WriteLine("[{0}, {1}, {2}]", prenom, nom, age);
58. }
59. }
60.
61.}
Nous testons la nouvelle classe avec le programme suivant :
1. using System;
2.
3. namespace Chap2 {
4. class Program {
5. static void Main(string[] args) {
6. Personne p = new Personne("Jean", "Michelin", 34);
7. Console.Out.WriteLine("p=(" + p.GetPrenom() + "," + p.GetNom() + "," + p.GetAge() + ")");
8. p.SetAge(56);
9. Console.Out.WriteLine("p=(" + p.GetPrenom() + "," + p.GetNom() + "," + p.GetAge() + ")");
10. }
11. }
12.}
et nous obtenons les résultats :
1. Constructeur Personne(string, string, int)
2. p=(Jean,Michelin,34)
3. p=(Jean,Michelin,56)

2.1.14 Les propriétés
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 :
1. using System;
2.
3. namespace Chap2 {
4. public class Personne {
5. // attributs
6. private string prenom;
7. private string nom;
8. private int age;
9.
10. // constructeurs
11. public Personne(String p, String n, int age) {
12. Initialise(p, n, age);
13. }
14. public Personne(Personne p) {
15. Initialise(p);
16. }
17.
18. // méthode
19. public void Initialise(string p, string n, int age) {
20. this.prenom = p;
21. this.nom = n;
22. this.age = age;
23. }
24.
25. public void Initialise(Personne p) {
26. prenom = p.prenom;
27. nom = p.nom;
28. age = p.age;
29. }
30.
31. // propriétés
32. public string Prenom {
33. get { return prenom; }
34. set {
35. // prénom valide ?
36. if (value == null || value.Trim().Length == 0) {
37. throw new Exception("prénom (" + value + ") invalide");
38. } else {
39. prenom = value;
40. }
41. }//if
42. }//prenom
43.
44. public string Nom {
45. get { return nom; }
46. set {
47. // nom valide ?
48. if (value == null || value.Trim().Length == 0) {
49. throw new Exception("nom (" + value + ") invalide");
50. } else { nom = value; }
51. }//if
52. }//nom
53.
54.
55. public int Age {
56. get { return age; }
57. set {
58. // age valide ?
59. if (value >= 0) {
60. age = value;
61. } else
62. throw new Exception("âge (" + value + ") invalide");
63. }//if
64. }//age
65.
66. // méthode
67. public void Identifie() {
68. Console.WriteLine("[{0}, {1}, {2}]", prenom, nom, age);
69. }
70. }
71.
72.}

Une propriété permet de lire (get) ou de fixer (set) la valeur d'un attribut. Une propriété est déclarée comme suit :
public Type Propriété{
get {...}
set {...}
}
où Type doit être le type de l'attribut géré par la propriété. Elle peut avoir deux méthodes appelées get et set. La méthode get est
habituellement chargée de rendre la valeur de l'attribut qu'elle gère (elle pourrait rendre autre chose, rien ne l'empêche). La méthode
set  reçoit un paramètre appelé  value  qu'elle affecte normalement à l'attribut qu'elle gère. Elle peut en profiter pour faire des
vérifications sur la validité de la valeur reçue et éventuellement lancer un 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 :
1. using System;
2.
3. namespace Chap2 {
4. class Program {
5. static void Main(string[] args) {
6. Personne p = new Personne("Jean", "Michelin", 34);
7. Console.Out.WriteLine("p=(" + p.Prenom + "," + p.Nom + "," + p.Age + ")");
8. p.Age = 56;
9. Console.Out.WriteLine("p=(" + p.Prenom + "," + p.Nom + "," + p.Age + ")");
10. try {
11. p.Age = -4;
12. } catch (Exception ex) {
13. Console.Error.WriteLine(ex.Message);
14. }//try-catch
15. }
16. }
17.}
Dans l'instruction
Console.Out.WriteLine("p=(" + p.Prenom + "," + p.Nom + "," + p.Age + ")");

on cherche à avoir les valeurs des propriétés Prenom, Nom et Age de la personne p. C'est la méthode get de ces propriétés qui est
alors appelée et qui rend la valeur de l'attribut qu'elles gèrent.
Dans l'instruction
p.Age=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.
L'exécution du programme de test précédent donne les résultats suivants :
1. p=(Jean,Michelin,34)
2. p=(Jean,Michelin,56)
3. âge (-4) invalide
Les propriétés nous permettent donc de manipuler des attributs privés comme s'ils étaient publics. Une autre caractéristique des
propriétés est qu'elles peuvent être utilisées conjointement avec un constructeur selon la syntaxe suivante :
Classe objet=new Classe (...) {Propriété1=val1, Propriété2=val2, ...}
Cette syntaxe est équivalente au code suivant :
1. Classe objet=new Classe(...);
2. objet.Propriété1=val1;
3. objet.Propriété2=val2;
4. ...
L'ordre des propriétés n'importe pas. Voici un exemple.

La classe Personne se voit ajouter un nouveau constructeur sans paramètres :
1. public Personne() {
2. }
Le constructeur n'initialise pas les membres de l'objet. C'est ce qu'on appelle le constructeur par défaut. C'est lui qui est utilisé
lorsque la classe ne définit aucun constructeur.
Le code suivant crée et initialise (ligne 6) une nouvelle Personne avec la syntaxe présentée précédemment :
1. using System;
2.
3. namespace Chap2 {
4. class Program {
5. static void Main(string[] args) {
6. Personne p2 = new Personne { Age = 7, Prenom = "Arthur", Nom = "Martin" };
7. Console.WriteLine("p2=({0},{1},{2})", p2.Prenom, p2.Nom, p2.Age);
8. }
9. }
10.}
Ligne 6 ci-dessus, c'est le constructeur sans paramètres Personne() qui est utilisé. Dans ce cas particulier, on aurait pu aussi écrire
Personne p2 = new Personne() { Age = 7, Prenom = "Arthur", Nom = "Martin" };
mais les parenthèses du constructeur Personne() sans paramètres ne sont pas obligatoires dans cette syntaxe.
Les résultats de l'exécution sont les suivants :
p2=(Arthur,Martin,7)
Dans beaucoup de cas, les méthodes get et set d'une propriété se contentent de lire et écrire un champ privé sans autre traitement.
On peut alors, dans ce scénario, utiliser une propriété automatique déclarée comme suit :
public Type Propriété{ get ; set ; }
Le champ privé associé à la propriété n'est pas déclaré. Il est automatiquement généré par le compilateur. On y accède que via sa
propriété. Ainsi, au lieu d'écrire :
private string prenom;
...
// propriété associée
public string Prenom {
get { return prenom; }
set {
// prénom valide ?
if (value == null || value.Trim().Length == 0) {
throw new Exception("prénom (" + value + ") invalide");
} else {
prenom = value;
}
}//if
}//prenom
on pourra écrire :
public string Prenom {get; set;}
sans déclarer le champ privé prenom. La différence entre les deux propriétés précédentes est que la première vérifie la validité du
prénom dans le set, alors que la deuxième ne fait aucune vérification.
Utiliser la propriété automatique Prenom revient à déclarer un champ Prenom public :

public string Prenom;
On peut se demander s'il y a une différence entre les deux déclarations. Déclarer public un champ d'une classe est déconseillé. Cela
rompt avec le concept d'encapsulation de l'état d'un objet, état qui doit être privé et exposé par des méthodes publiques.

Si la propriété automatique est déclarée virtuelle, elle peut alors être redéfinie dans une classe fille :
1. class Class1 {
2. public virtual string Prop { get; set; }
3. }
1. class Class2 : Class1 {
2. public override string Prop { get { return base.Prop; } set {... } }
3. }
Ligne 2 ci-dessus, la classe fille  Class2  peut mettre dans le  set,  du code vérifiant la validité de la valeur affectée à la propriété
automatique base.Prop de la classe mère Class1.

Publié par Drupal french Study