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?
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:
Classes conçues pour être étendues et avec suffisamment de documentation pour décrire la procédure à suivre
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".
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.
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.
Il y a 3 cas d'utilisation où vous pouvez aller pour 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.
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é.
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" .
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.
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.
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.
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.
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.