DotnetDojo

Développer des applications modernes avec les technologies Microsoft et Open source

  • Blog
  • Vidéos
  • Formations
  • Outils

Faut-il utiliser les interfaces ou les classes abstraites ? (et comment choisir entre les deux)

choisir_300x200
Dans cet article, je vais vous expliquer comment choisir entre les interfaces et les classes abstraites pour écrire du code en C#.
Cette décision est importante car elle a des conséquences sur le code et sur la facilité d’utilisation par la suite.

Comme tout développeur, a un moment donné, vous avez du vous poser la question : est-ce que je dois créer plutôt une interface ou bien une classe abstraite pour ce nouveau type ? Comment faire pour choisir entre les deux ? Quelles sont les conséquences si je me trompe ?
Rassurez-vous, nous allons parler de tout ça dans cet article.

Je rencontre souvent des débutants qui utilisent des interfaces un peu partout. C’est à la mode, alors ils en mettent un peu partout dans le code, même quand ça n’est pas nécessaire. L’exemple le plus classique que je vois souvent : créer une interface pour une seule classe. Et quand je demande pourquoi le développeur a fait ce choix, j’ai souvent des réponses un peu floues.

Qu’est ce qu’une interface en C# ?

En C#, une interface permet de décrire un « contrat ».
Elle ne peut contenir que des méthodes, des propriétés ou des événements. Les membres d’une interface sont forcément publiques.

Une classe peut alors « implémenter » une interface. C’est-à-dire qu’elle s’engage à implémenter les méthodes décrites dans l’interface.

En C#, une classe peut implémenter plusieurs interfaces différentes.

Qu’est ce qu’une classe abstraite en C# ?

Une classe abstraite est une classe partiellement définie. Elle comporte, au moins, une méthode abstraite qui n’a pas de corps (pas de code).

Une classe abstraite peut contenir tous les éléments d’une classe « normale » : champs (variables), événements, propriétés, méthodes…

Par contre, une classe abstraite peut comporter un état. Comme elle peut contenir des membres (variables), il est possible d’affecter un état à cette classe.

En C#, une classe peut hériter que d’une seule autre classe.

Quelles sont les différences entre les interfaces et les classes abstraites en C# ?

Comme nous l’avons vu dans les paragraphes précédents, les classes abstraites sont des classes partiellement définies.

Par rapport à une interface, une classe abstraite peut avoir :

  • un état (des champs – les variables)
  • un comportement (du code)

Une classe pourra :

  • Implémenter une ou plusieurs interfaces
  • Hériter d’une seule classe (abstraite ou non)

Comment choisir entre interface ou classe abstraite ?

Une classe abstraite est généralement utilisée pour construire des classes similaires. Elles auront toutes une implémentation en commun, celle de la classe abstraite.

Une interface est généralement utilisée pour définir des capacités (le « contrat »), même si les classes n’ont pas grand chose en commun.

Pour vous aider, posez-vous les questions suivantes : Est-ce que mes classes auront un comportement commun ?

Exemple dans .NET

Dans le framework .NET, vous avez des dizaines de classes qui implémentent IEnumerable. Cela vous permet d’utiliser foreach sur une collection d’objets.

Si vous y regardez de plus prêt, les classes qui implémentent IEnumerable n’ont parfois rien en commun. Par contre, vous pouvez énumérer des collections d’entiers ou bien des collections de chaines.

Est-ce que ces classes ont un comportement commun ? La réponse est Non. Les entiers et les chaines n’ont pas grand chose en commun (en tout cas du point de vue énumération).

Pour les classes abstraites, je vous propose l’exemple suivant. Nous avons une classe de base AbstractLogger. Celle-ci contient des méthodes « Info », « Error », « Warn »… Voici le code correspondant :
[csharp] public abstract class AbstractLogger
{
public void Info(string msg)
{
WriteMessage("INFO : " + msg);
}

public void Error(string msg)
{
WriteMessage("ERROR : " + msg);
}

public void Warn(string msg)
{
WriteMessage("WARN : " + msg);
}

public abstract void WriteMessage(string text);
}
[/csharp]

Comme nous le voyons, la classe AbstractLogger propose une implémentation partielle.
Si nous souhaitons créer un logger pour la console, nous pourrions écrire quelque chose comme ça :

[csharp] public class ConsoleLogger : AbstractLogger
{
public override void WriteMessage(string text)
{
Console.WriteLine(text);
}
}
[/csharp]

Nous pourrions bien sûr créer une classe pour écrire dans un fichier ou bien une autre pour écrire en base de données. Toutes ces classes partageraient le même comportement par défaut (les méthodes Info, Warn et Error).

Est-ce que ces classes ont un comportement commun ? La réponse est Oui car toutes les classes partagent les mêmes méthodes de formatage (Info, Error, Warn).

Si vous souhaitez aller plus loin, je vous invite à découvrir le programme de la formation Apprendre CSharp en 24 heures chrono.

Besoin de résultats rapides ?

Découvrez les formations vidéos que je propose :

  

 

Formations en présentiel (dans toute la France)

Découvrez également les formations C# et .NET que je donne en présentiel (en France)

Comments

  1. Christophe says

    12 décembre 2014 at 19 h 26 min

    Bonjour Pascal,

    Je me permet de donner mon avis sur la question 🙂

    Ancien partisan des classes abstraites, je suis de moins convaincu de leur utilité pour écrire du code propre.
    Pour écrire des tests unitaires, l’utilisation d’interfaces va garantir le découplage de la classe testée avec ses dépendances.
    A l’opposé, l’héritage risque de casser l’encapsulation. On sera obligé de tester le comportement de la classe de base lorsque l’on testera la classe dérivée.
    Toute modification de la classe de base peut causer des régressions sur les tests de la classe dérivée, qui ne seront plus véritablement unitaires…

    Ce n’est donc pas aberrant d’avoir une interface associée à une seule classe de prod.

    • Pascal Lacroix says

      22 décembre 2014 at 16 h 52 min

      Merci Christophe pour votre retour.

      En fait, je disais que très souvent je rencontre des développeurs qui crées des interfaces sans trop savoir pourquoi. Ce n’est pas le fait d’avoir une interface pour une classe qui est aberrant mais plutôt le fait de ne pas savoir pourquoi créer une interface (la réponse, c’est souvent, je ne sais pas trop, je vois ça un peu partout…).

A propos de DotnetDojo

Pascal Lacroix

Je m’appelle Pascal et je suis passionné par le développement logiciel, l’efficacité et l’entrepreneuriat. Sur DotnetDojo, je vous propose des méthodes pour apprendre à développer des applications modernes avec les technologies Microsoft et Open Source.

En savoir plus

Liens complémentaires

  • A propos de DotnetDojo
  • 18 principes pour professionnaliser le développement logiciel
  • Boite à outils du développeur
  • Tous les articles
  • Liste des formations
  • Contact

Copyright 2019 Jupiteo · Mentions légales · Contact · CGV · Offres d'emploi .NET · Formations Dotnet