L'héritage en C sharp: Généralités + Construction d'un objet Enseignant

2.2.1 Généralités
Nous abordons ici la notion d'héritage. Le but de l'héritage est de "personnaliser" une classe existante pour qu'elle satisfasse à nos
besoins. 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 d'héritage qui nous permet cela.
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 :
1. using System;
2.
3. namespace Chap2 {
4. public class Personne {
5.
6. // attributs de classe
7. private static long nbPersonnes;
8. public static long NbPersonnes {
9. get { return nbPersonnes; }
10. }
11.
12. // attributs d'instance
13. private string prenom;
14. private string nom;
15. private int age;
16.
17. // constructeurs
18. public Personne(String prenom, String nom, int age) {
19. Nom = nom;
20. Prenom = prenom;
21. Age = age;
22. nbPersonnes++;
23. Console.WriteLine("Constructeur Personne(string, string, int)");
24. }
25. public Personne(Personne p) {
26. Nom = p.Nom;
27. Prenom = p.Prenom;
28. Age = p.Age;
29. nbPersonnes++;
30. Console.WriteLine("Constructeur Personne(Personne)");
31. }
32.
33. // propriétés
34. public string Prenom {
35. get { return prenom; }
36. set {
37. // prénom valide ?
38. if (value == null || value.Trim().Length == 0) {
39. throw new Exception("prénom (" + value + ") invalide");
40. } else {
41. prenom = value;
42. }
43. }//if
44. }//prenom
45.
46. public string Nom {
47. get { return nom; }
48. set {
49. // nom valide ?
50. if (value == null || value.Trim().Length == 0) {
51. throw new Exception("nom (" + value + ") invalide");
52. } else { nom = value; }
53. }//if
54. }//nom
55.
56. public int Age {
57. get { return age; }
58. set {
59. // age valide ?
60. if (value >= 0) {
61. age = value;
62. } else
63. throw new Exception("âge (" + value + ") invalide");
64. }//if
65. }//age
66.
67. // propriété
68. public string Identite {
69. get { return String.Format("[{0}, {1}, {2}]", prenom, nom, age);}
70. }
71. }
72.
73.}
La méthode Identifie a été remplacée par la propriété Identite en lecture seule et qui identifie la personne. Nous créons une classe
Enseignant  héritant de la classe Personne :
1. using System;
2.
3. namespace Chap2 {
4. class Enseignant : Personne {
5. // attributs
6. private int section;
7.
8. // constructeur
9. public Enseignant(string prenom, string nom, int age, int section)
10. : base(prenom, nom, age) {
11. // on mémorise la section via la propriété Section
12. Section = section;
13. // suivi
14. Console.WriteLine("Construction Enseignant(string, string, int, int)");
15. }//constructeur
16.
17. // propriété Section
18. public int Section {
19. get { return section; }
20. set { section = value; }
21. }// Section
22.
23. }
24.}

La classe Enseignant rajoute aux méthodes et attributs de la classe Personne :
 ligne 4 : la classe Enseignant dérive de la classe Personne
 ligne 6 : un attribut section qui est le n° de section auquel appartient l'enseignant dans le corps des enseignants (une section
par discipline en gros). Cet attribut privé est accessible via la propriété publique Section des lignes 18-21
 ligne 9 : un nouveau constructeur permettant d'initialiser tous les attributs d'un enseignant

2.2.2 Construction d'un objet Enseignant
Une classe fille  n'hérite pas des constructeurs  de sa classe Parent. Elle doit alors définir ses propres constructeurs. Le
constructeur de la classe Enseignant est le suivant :
1. // constructeur
2. public Enseignant(string prenom, string nom, int age, int section)
3. : base(prenom, nom, age) {
4. // on mémorise la section
5. Section = section;
6. // suivi
7. Console.WriteLine("Construction enseignant(string, string, int, int)");
8. }//constructeur
La déclaration
public Enseignant(string prenom, string nom, int age, int section)
: base(prenom, nom, age) {
déclare que le constructeur reçoit quatre paramètres prenom, nom, age, section et en passe trois (prenom,nom,age) à sa classe de base, ici la
classe Personne. On sait que cette classe a un constructeur Personne(string, string, int) qui va permettre de construire une personne avec les paramètres passsés (prenom,nom,age). Une fois la construction de la classe de base terminée, la construction de l'objet Enseignant se
poursuit par l'exécution du corps du constructeur :
// on mémorise la section
Section = section;
On notera qu'à gauche du signe =, ce n'est pas l'attribut section de l'objet qui a été utilisé, mais la propriété Section qui lui est associée.
Cela permet au constructeur de profiter des éventuels contrôles de validité que pourrait faire cette méthode. Cela évite de placer
ceux-ci à deux endroits différents : le constructeur et la propriété.
En résumé, le constructeur d'une classe dérivée :
 passe à sa classe de base les paramètres dont celle-ci a besoin pour se construire
 utilise les autres paramètres pour initialiser les attributs qui lui sont propres
On aurait pu préférer écrire :
// constructeur
  public Enseignant(string prenom, string nom, int age, int section){
    this.prenom=prenom;
this.nom=nom;
this.age=age;
   this.section=section;
  }
C'est impossible. La classe Personne a déclaré privés (private) ses trois champs prenom, nom et age. Seuls des objets de la même classe
ont un accès direct à ces champs. Tous les autres objets, y compris des objets fils comme ici, doivent passer par des méthodes
publiques pour y avoir accès. Cela aurait été différent si la classe Personne avait déclaré protégés (protected) les trois champs : elle
autorisait alors des classes dérivées à avoir un accès direct aux trois champs. Dans notre exemple, utiliser le constructeur de la classe
parent était donc la bonne solution et c'est la méthode habituelle : lors de la construction d'un objet fils, on appelle d'abord le
constructeur de l'objet parent puis on complète les initialisations propres cette fois à l'objet fils (section dans notre exemple).
Tentons un premier programme de test [Program.cs] :

1. using System;
2.
3. namespace Chap2 {
4. class Program {
5. static void Main(string[] args) {
6. Console.WriteLine(new Enseignant("Jean", "Dupont", 30, 27).Identite);
7. }
8. }
9. }
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.
L'ensemble du projet est le suivant :

L'héritage en C sharp: Généralités + Construction d'un objet Enseignant
L'héritage en C sharp: Généralités + Construction d'un objet Enseignant
Les résultats obtenus sont les suivants :
1. Constructeur Personne(string, string, int)
2. Construction Enseignant(string, string, int, int)
3. [Jean, Dupont, 30]
On voit que :
 un objet Personne (ligne 1) a été construit avant l'objet Enseignant (ligne 2)
 l'identité obtenue est celle de l'objet Personne

Publié par Drupal french Study