Quand utiliser une classe abstraite ou une interface en C #

Lors de la conception d'applications, il est important de savoir quand utiliser une classe abstraite et quand utiliser une interface. Bien que les classes abstraites et les interfaces semblent similaires à certains égards, il existe des différences clés qui détermineront quel est le meilleur choix pour ce que vous essayez d'accomplir. Dans cet article de blog, je discuterai de ces différences et de la manière de décider quand les utiliser.

La réponse courte: une classe abstraite vous permet de créer des fonctionnalités que les sous-classes peuvent implémenter ou remplacer. Une interface vous permet uniquement de définir des fonctionnalités, pas de les implémenter. Et alors qu'une classe ne peut étendre qu'une seule classe abstraite, elle peut tirer parti de plusieurs interfaces. 

Explication de la classe abstraite C #

Une classe abstraite est un type spécial de classe qui ne peut pas être instancié. Une classe abstraite est conçue pour être héritée par des sous-classes qui implémentent ou remplacent ses méthodes. En d'autres termes, les classes abstraites sont soit partiellement implémentées soit pas du tout implémentées. Vous pouvez avoir des fonctionnalités dans votre classe abstraite - les méthodes d'une classe abstraite peuvent être à la fois abstraites et concrètes. Une classe abstraite peut avoir des constructeurs - c'est une différence majeure entre une classe abstraite et une interface. Vous pouvez tirer parti des classes abstraites pour concevoir des composants et spécifier un certain niveau de fonctionnalité commune qui doit être implémenté par les classes dérivées.

Interface C # expliquée

Une interface est essentiellement un contrat - elle n'a aucune implémentation. Une interface ne peut contenir que des déclarations de méthode; il ne peut pas contenir de définitions de méthode. Vous ne pouvez pas non plus avoir de données de membre dans une interface. Alors qu'une classe abstraite peut contenir des définitions de méthode, des champs et des constructeurs, une interface ne peut avoir que des déclarations d'événements, de méthodes et de propriétés. Les méthodes déclarées dans une interface doivent être implémentées par les classes qui implémentent l'interface. Notez qu'une classe peut implémenter plus d'une interface mais étendre une seule classe. La classe qui implémente l'interface doit implémenter tous ses membres. Comme une classe abstraite, une interface ne peut pas être instanciée.

Dois-je utiliser une classe abstraite ou une interface?

Les classes abstraites vous offrent la flexibilité d'avoir certaines méthodes concrètes et d'autres méthodes que les classes dérivées devraient implémenter. En revanche, si vous utilisez des interfaces, vous devrez implémenter toutes les méthodes de la classe qui étend l'interface. Une classe abstraite est un bon choix si vous avez des projets d'expansion future - c'est-à-dire si une expansion future est probable dans la hiérarchie des classes. Si vous souhaitez prendre en charge une extension future lors de l'utilisation d'interfaces, vous devrez étendre l'interface et en créer une nouvelle.

Sur une note différente, il est facile d'ajouter une nouvelle interface à la hiérarchie si besoin est. Cependant, si vous avez déjà une classe abstraite dans votre hiérarchie, vous ne pouvez pas en ajouter une autre, c'est-à-dire que vous ne pouvez ajouter une classe abstraite que si aucune n'est disponible. Vous devez utiliser une interface si vous souhaitez un contrat sur un comportement ou une fonctionnalité. Vous ne devez pas utiliser d'interface si vous devez écrire le même code pour les méthodes d'interface. Dans ce cas, vous devez utiliser une classe abstraite, définir la méthode une fois et la réutiliser si nécessaire. Utilisez des interfaces pour découpler le code de votre application de ses implémentations spécifiques, ou pour restreindre l'accès aux membres d'un certain type.

Comme l'indique la documentation de Microsoft sur les interfaces:

En utilisant des interfaces, vous pouvez, par exemple, inclure le comportement de plusieurs sources dans une classe. Cette fonctionnalité est importante en C # car le langage ne prend pas en charge l'héritage multiple de classes. En outre, vous devez utiliser une interface si vous souhaitez simuler l'héritage pour les structures, car elles ne peuvent pas réellement hériter d'une autre structure ou classe.

Implémentations d'interface implicites et explicites

Les interfaces peuvent être implémentées implicitement ou explicitement. Laissez-moi vous expliquer en quoi ces deux implémentations diffèrent. Considérez une interface appelée IBusinessLogic.

interface publique IBusinessLogic

{

   void Initialize ();

}

La classe nommée suivante BusinessLogicimplémente l' IBusinessLogicinterface.

classe publique BusinessLogic: IBusinessLogic

{

   public void Initialize ()

   {

       // Un peu de code

   }

}

Vous pouvez créer une instance de la BusinessLogicclasse explicitement, puis appeler la Initialize()méthode comme indiqué ci-dessous.

 IBusinessLogic businessLogic = nouveau BusinessLogic ();

businessLogic.Initialize ();

L'extrait de code suivant illustre comment vous pouvez implémenter l' IBusinessLogicinterface de manière implicite.

classe publique BusinessLogic: IBusinessLogic

{

   void IBusinessLogic.Initialize ()

   {

   }

}

Vous pouvez maintenant appeler la Initialize()méthode de la même manière en utilisant une référence à l' IBusinessLogicinterface. La différence entre les deux approches est que lorsque vous implémentez l'interface explicitement dans votre classe, vous êtes contraint d'appeler une méthode de votre interface en utilisant une référence à l'interface uniquement. Par conséquent, l'extrait de code suivant ne fonctionnerait pas, c'est-à-dire ne serait pas compilé.

 BusinessLogic businessLogic = nouveau BusinessLogic ();

businessLogic.Initialize ();

Comment faire plus en C #:

  • Quand utiliser une classe abstraite ou une interface en C #
  • Comment travailler avec AutoMapper en C #
  • Comment utiliser les expressions lambda en C #
  • Comment travailler avec les délégués Action, Func et Predicate en C #
  • Comment travailler avec des délégués en C #
  • Comment implémenter un simple logger en C #
  • Comment travailler avec des attributs en C #
  • Comment travailler avec log4net en C #
  • Comment implémenter le modèle de conception de référentiel en C #
  • Comment travailler avec la réflexion en C #
  • Comment travailler avec Filesystemwatcher en C #
  • Comment effectuer une initialisation différée en C #
  • Comment travailler avec MSMQ en C #
  • Comment travailler avec des méthodes d'extension en C #
  • Comment utiliser les expressions lambda en C #
  • Quand utiliser le mot clé volatile en C #
  • Comment utiliser le mot clé yield en C #
  • Comment implémenter le polymorphisme en C #
  • Comment créer votre propre planificateur de tâches en C #
  • Comment travailler avec RabbitMQ en C #
  • Comment travailler avec un tuple en C #
  • Explorer les méthodes virtuelles et abstraites en C #