J'ai récemment dû mettre à jour une classe de base abstraite sur un OSS que j'utilisais pour qu'il soit plus testable en les rendant virtuels (je ne pouvais pas utiliser une interface car elle en combinait deux). Cela m'a fait penser si je devais marquer toutes les méthodes dont j'avais besoin comme virtuelles, ou si je devrais marquer chaque méthode / propriété publique virtuelle. Je suis généralement d' accord avec Roy Osherove pour dire que chaque méthode doit être rendue virtuelle, mais je suis tombé sur cet article qui m'a fait réfléchir à savoir si c'était nécessaire ou non . Je vais cependant limiter cela aux classes abstraites pour plus de simplicité (si toutes les méthodes publiques concrètes doivent être virtuelles est particulièrement discutable, j'en suis sûr).
Je pouvais voir où vous pourriez autoriser une sous-classe à utiliser une méthode, mais ne pas vouloir qu'elle remplace l'implémentation. Cependant, tant que vous croyez que le principe de substitution de Liskov sera respecté, pourquoi ne permettriez-vous pas qu'il soit annulé? En la marquant abstraite, vous forcez de toute façon une certaine surcharge, donc, il me semble que toutes les méthodes publiques à l'intérieur d'une classe abstraite devraient en effet être marquées virtuelles.
Cependant, je voulais demander au cas où il y aurait quelque chose auquel je ne penserais peut-être pas. Toutes les méthodes publiques d'une classe abstraite doivent-elles être rendues virtuelles?
la source
Réponses:
Par exemple, parce que je veux que l'implémentation squelette d'un algorithme soit fixe, et que seules des parties spécifiques soient (re) définies par des sous-classes. Ceci est largement connu sous le nom de modèle de méthode de modèle (souligné ci-dessous par moi):
Mise à jour
Quelques exemples concrets de projets sur lesquels j'ai travaillé:
Dans les deux premiers cas, l'implémentation héritée d'origine utilisait la stratégie , ce qui a donné lieu à de nombreux codes dupliqués, qui bien sûr au fil des ans ont augmenté de subtiles différences ici et là, contenaient de nombreux bogues dupliqués ou légèrement différents et étaient très difficiles à maintenir. La refactorisation vers la méthode de modèle (et certaines autres améliorations, comme l'utilisation d'annotations Java) a réduit la taille du code d'environ 40 à 70%.
Ce ne sont que les exemples les plus récents qui me viennent à l'esprit. Je pourrais citer plus de cas de presque tous les projets sur lesquels j'ai travaillé jusqu'à présent.
la source
Il est parfaitement raisonnable et parfois souhaitable d'avoir des méthodes non virtuelles dans une classe de base abstraite; ce n'est pas parce que c'est une classe abstraite que toutes ses parties doivent être utilisables de manière polymorphe.
Par exemple, vous souhaiterez peut-être utiliser l'idiome `` polymorphisme non virtuel '', selon lequel une fonction est appelée de manière polymorphe à partir d'une fonction membre non virtuelle, afin de garantir que certaines conditions préalables ou postconditions sont remplies avant l'appel de la fonction virtuelle.
la source
Il suffit qu'une classe contienne UNE méthode virtuelle pour que la classe devienne abstraite. Vous voudrez peut-être faire attention aux méthodes que vous souhaitez virtualiser et aux autres, selon le type de polymorphisme que vous prévoyez d'utiliser.
la source
Demandez-vous à quoi sert une méthode non virtuelle dans une classe abstraite. Une telle méthode devrait avoir une implémentation pour la rendre utile. Mais si la classe a une implémentation, peut-elle encore être appelée une classe abstraite? Même si le langage / compilateur le permet, cela a-t-il un sens? Personnellement, je ne pense pas. Vous auriez une classe normale avec des méthodes abstraites que les descendants devraient implémenter.
Mon langage principal est Delphi, pas C #. Dans Delphi, si vous marquez un résumé de méthode, vous devez également le marquer comme virtuel ou le compilateur se plaint. Je n'ai pas suivi les derniers changements de langage de trop près, mais si des classes abstraites sont dans ou viendraient à Delphi, je m'attendrais à ce que le compilateur se plaigne de toutes les méthodes non virtuelles, de toutes les méthodes privées et de toutes les implémentations de méthodes pour une classe marquée abstraite au niveau de la classe.
la source
abstract
, vous devez également marquer toute la classeabstract
.Vous ne rendez pas certaines méthodes virtuelles parce que vous ne croyez pas que ce soit le cas. De plus, en rendant certaines méthodes non virtuelles, vous signalez aux héritiers quelles méthodes doivent être implémentées.
Personnellement, je ferai souvent des surcharges de méthodes qui existent pour des raisons de commodité non virtuelles afin que les utilisateurs de la classe puissent avoir des valeurs par défaut cohérentes et que les implémenteurs ne soient même pas capables de commettre l'erreur de briser ce comportement implicite.
la source