web-dev-qa-db-fra.com

De bonnes raisons pour interdire l'héritage en Java?

Quelles sont les bonnes raisons d'interdire l'héritage en Java, par exemple en utilisant des classes finales ou des classes utilisant un seul constructeur privé sans paramètre? Quelles sont les bonnes raisons de rendre une méthode finale?

155
cretzel

Votre meilleure référence ici est le point 19 de l'excellent livre de Joshua Bloch, "Effective Java", intitulé "Concevez et documentez l'héritage ou interdisez-le". (Il s'agit du point 17 dans la deuxième édition et du point 15 dans la première édition.) Vous devriez vraiment le lire, mais je vais résumer.

L'interaction des classes héritées avec leurs parents peut être surprenante et imprévisible si l'ancêtre n'a pas été conçu pour en hériter.

Les classes doivent donc être de deux types:

  1. Classes conçues pour être étendues et avec suffisamment de documentation pour décrire la procédure à suivre

  2. Classes marquées finale

Si vous écrivez du code purement interne, cela peut être un peu excessif. Cependant, l’effort supplémentaire impliqué dans l’ajout de cinq caractères à un fichier de classe est très faible. Si vous écrivez uniquement pour la consommation interne, un futur codeur peut toujours supprimer le "final" - vous pouvez le considérer comme un avertissement disant "cette classe n'a pas été conçue avec l'héritage".

170
DJClayworth

Vous voudrez peut-être rendre une méthode finale afin que les classes qui la surchargent ne puissent pas changer le comportement pris en compte par d'autres méthodes. Les méthodes appelées dans les constructeurs sont souvent déclarées finales afin d'éviter toute mauvaise surprise lors de la création d'objets.

22
Bill the Lizard

Une des raisons pour rendre une classe finale serait si vous vouliez forcer la composition avant l’héritage. Ceci est généralement souhaitable pour éviter un couplage étroit entre les classes.

17
John Topley

Il y a 3 cas d'utilisation où vous pouvez aller pour les méthodes finales.

  1. Pour éviter que la classe dérivée ne remplace une fonctionnalité de classe de base particulière.
  2. C'est pour des raisons de sécurité, où la classe de base fournit certaines fonctionnalités essentielles du framework, où la classe dérivée n'est pas supposée la changer.
  3. Les méthodes finales sont plus rapides que les méthodes d'instance, car le concept de table virtuelle n'est pas utilisé pour les méthodes finales et privées. Donc, là où il y a une possibilité, essayez d'utiliser les méthodes finales.

But pour faire une finale de classe:

Pour que personne ne puisse étendre ces classes et changer leur comportement.

Ex.: Classe Wrapper Integer est une classe finale. Si cette classe n'est pas finale, chacun peut étendre Integer dans sa propre classe et modifier le comportement de base de la classe entière. Pour éviter cela, Java a fait de toutes les classes wrapper les classes finales.

13
user1923551

vous voudrez peut-être créer des objets immuables ( http://en.wikipedia.org/wiki/Immutable_object ), vous voudrez peut-être créer un singleton ( http: //en.wikipedia. org/wiki/Singleton_pattern ), ou vous pouvez empêcher quelqu'un de remplacer la méthode pour des raisons d'efficacité, de sécurité ou de sécurité.

12
Ray Tayek

L'héritage est comme une tronçonneuse - très puissant, mais affreux entre de mauvaises mains. Soit vous concevez une classe dont on héritera (ce qui peut limiter la flexibilité et prendre beaucoup plus de temps) ou vous devez l’interdire.

Voir Effective Java Articles 16 et 17 de la 2e édition, ou mon article de blog "Impôt sur les successions" .

6
Jon Skeet

Hmmm ... Je peux penser à deux choses:

Vous pourriez avoir une classe qui traite de certains problèmes de sécurité. En le sous-classant et en fournissant à votre système la version de ce dernier, un attaquant peut contourner les restrictions de sécurité. Par exemple. votre application peut prendre en charge des plugins et si un plugin peut simplement sous-classer vos classes pertinentes pour la sécurité, il peut utiliser cette astuce pour en faire entrer une version sous-classée. Cependant, c’est plutôt quelque chose que Sun doit gérer en ce qui concerne les applets et autres, peut-être pas un cas aussi réaliste.

Une solution beaucoup plus réaliste consiste à éviter qu'un objet ne devienne mutable. Par exemple. puisque les chaînes sont immuables, votre code peut garder des références en toute sécurité

 String blah = someOtherString;

au lieu de copier la chaîne en premier. Toutefois, si vous pouvez sous-classer String, vous pouvez y ajouter des méthodes permettant de modifier la valeur de la chaîne. Aucun code ne peut désormais plus compter sur le fait que la chaîne restera la même si elle ne fait que copier la chaîne comme ci-dessus. chaîne.

4
Mecki

En outre, si vous écrivez une classe source fermée commerciale, vous ne voudrez peut-être pas que les utilisateurs puissent modifier les fonctionnalités ultérieurement, en particulier si vous devez fournir une assistance et que les utilisateurs ont ignoré votre méthode et se plaignent de l'appel de cette méthode. résultats inattendus.

1
DavidG

Si vous marquez les classes et les méthodes comme finales, vous remarquerez peut-être un léger gain de performances, car le moteur d’exécution n’a pas à rechercher la bonne méthode de classe à appeler pour un objet donné. Les méthodes non finales sont marquées comme virtuelles afin de pouvoir être correctement étendues si nécessaire. Les méthodes finales peuvent être directement liées ou compilées en ligne dans la classe.

1
seanalltogether

Empêcher les gens de faire des choses qui pourraient créer de la confusion chez eux et chez les autres. Imaginez une bibliothèque de physique où vous avez des constantes ou des calculs définis. Sans utiliser le mot-clé final, quelqu'un pourrait arriver et redéfinir les calculs de base ou les constantes qui ne devraient JAMAIS changer.

1
Anson Smith

Vous voulez rendre une méthode finale pour que le remplacement des classes ne modifie pas son comportement. Lorsque vous souhaitez pouvoir modifier le comportement, rendez la méthode publique. Lorsque vous substituez une méthode publique, elle peut être modifiée.

0
Alexander Robinson