'>

Les classes abstraites en C sharp

Une classe abstraite est une classe qu'on ne peut instancier. Il faut créer des classes dérivées qui elles pourront être instanciées.
On peut utiliser des classes abstraites pour factoriser le code d'une lignée de classes. Examinons le cas suivant :
1. using System;
2.
3. namespace Chap2 {
4. abstract class Utilisateur {
5. // champs
6. private string login;
7. private string motDePasse;
8. private string role;
9.
10. // constructeur
11. public Utilisateur(string login, string motDePasse) {
12. // on enregistre les informations
13. this.login = login;
14. this.motDePasse = motDePasse;
15. // on identifie l'utilisateur
16. role=identifie();
17. // identifié ?
18. if (role == null) {
19. throw new ExceptionUtilisateurInconnu(String.Format("[{0},{1}]", login, motDePasse));
20. }
21. }
22.
23. // toString
24. public override string ToString() {
25. return String.Format("Utilisateur[{0},{1},{2}]", login, motDePasse, role);
26. }
27.
28. // identifie
29. abstract public string identifie();
30. }
31.}
• lignes 11-21 : le contructeur de la classe  Utilisateur. Cette classe mémorise des informations sur l'utilisateur d'une
application web. Celle-ci a divers types d'utilisateurs authentifiés par un login / mot de passe (lignes 6-7). Ces deux
informations sont vérifiées auprès d'un service LDAP pour certains utilisateurs, auprès d'un SGBD pour d'autres, etc...
• lignes 13-14 : les informations d'authentification sont mémorisées
• ligne 16 : elles sont vérifiées par une méthode identifie. Parce que la méthode d'identification n'est pas connue, elle est
déclarée abstraite ligne 29 avec le mot clé abstract. La méthode identifie rend une chaîne de caractères précisant le rôle de
l'utilisateur (en gros ce qu'il a le droit de faire). Si cette chaîne est le pointeur null, une exception est lancée ligne 19.
• ligne 4 : parce qu'elle a une méthode abstraite, la classe elle-même est déclarée abstraite avec le mot clé abstract.
• ligne 29 : la méthode abstraite identifie n'a pas de définition. Ce sont les classes dérivées qui lui en donneront une.
• lignes 24-26 : la méthode ToString qui identifie une instance de la classe.
On suppose ici que le développeur veut avoir la maîtrise de la construction des instances de la classe  Utilisateur et des classes
dérivées, peut-être parce qu'il veut être sûr qu'une exception d'un certain type est lancée si l'utilisateur n'est pas reconnu (ligne 19).
Les classes dérivées pourront s'appuyer sur ce constructeur. Elles devront pour cela fournir la méthode identifie.
La classe ExceptionUtilisateurInconnu est la suivante :
1. using System;
2.
3. namespace Chap2 {
4. class ExceptionUtilisateurInconnu : Exception {
5. public ExceptionUtilisateurInconnu(string message) : base(message){
6. }
7. }
8. }
• ligne 3 : elle dérive de la classe Exception
• lignes 4-6 : elle n'a qu'un unique constructeur qui admet pour paramètre un message d'erreur. Celui-ci est passé à la classe
parent (ligne 5) qui a ce même constructeur.
Nous dérivons maintenant la classe Utilisateur dans la classe fille Administrateur :
1. namespace Chap2 {
2. class Administrateur : Utilisateur {
3. // constructeur
4. public Administrateur(string login, string motDePasse)
5. : base(login, motDePasse) {
6. }
7.
8. // identifie
9. public override string identifie() {
10. // identification LDAP
11. // ...
12. return "admin";
13. }
14. }
15.}
• lignes 4-6 : le constructeur se contente de passer à sa classe parent les paramètres qu'il reçoit
• lignes 9-12 : la méthode identifie de la classe Administrateur. On suppose qu'un administrateur est identifié par un système
LDAP. Cette méthode redéfinit la méthode identifie de sa classe parent. Parce qu'elle redéfinit une méthode abstraite, il
est inutile de mettre le mot clé override.
Nous dérivons maintenant la classe Utilisateur dans la classe fille Observateur :
1. namespace Chap2 {
2. class Observateur : Utilisateur{
3. // constructeur
4. public Observateur(string login, string motDePasse)
5. : base(login, motDePasse) {
6. }
7.
8. //identifie
9. public override string identifie() {
10. // identification SGBD
11. // ...
12. return "observateur";
13. }
14.
15. }
16.}
• lignes 4-6 : le constructeur se contente de passer à sa classe parent les paramètres qu'il reçoit
• lignes 9-13 : la méthode identifie de la classe Observateur. On suppose qu'un observateur est identifié par vérification de
ses données d'identification dans une base de données.
Au final, les objets Administrateur et Observateur sont instanciés par le même constructeur, celui de la classe parent Utilisateur. Ce
constructeur va utiliser la méthode identifie que ces classes fournissent.
Une troisième classe Inconnu dérive également de la classe Utilisateur :
1. namespace Chap2 {
2. class Inconnu : Utilisateur{
3.
4. // constructeur
5. public Inconnu(string login, string motDePasse)
6. : base(login, motDePasse) {
7. }
8.
9. //identifie
10. public override string identifie() {
11. // utilisateur pas connu
12. // ...
13. return null;
14. }
15.
16. }
17.}
• ligne 13 : la méthode identifie rend le pointeur null pour indiquer que l'utilisateur n'a pas été reconnu.
Un programme de test pourrait être le suivant :
1. using System;
2.
3. namespace Chap2 {
4. class Program {
5. static void Main(string[] args) {
6. Console.WriteLine(new Observateur("observer","mdp1"));
7. Console.WriteLine(new Administrateur("admin", "mdp2"));
8. try {
9. Console.WriteLine(new Inconnu("xx", "yy"));
10. } catch (ExceptionUtilisateurInconnu e) {
11. Console.WriteLine("Utilisateur non connu : "+ e.Message);
12. }
13. }
14. }
15.}
On notera que lignes 6, 7 et 9, c'est la méthode [Utilisateur].ToString() qui sera utilisée par la méthode WriteLine.
Les résultats de l'exécution sont les suivants :
1. Utilisateur[observer,mdp1,observateur]
2. Utilisateur[admin,mdp2,admin]
3. Utilisateur non connu : [xx,yy]
Publié par Drupal french Study