De bonnes raisons d'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 en utilisant un seul constructeur privé sans paramètres? Quelles sont les bonnes raisons de faire une méthode finale?
11 réponses
votre meilleure référence ici est L'article 19 de L'excellent Livre de Joshua Bloch "Java efficace", appelé "Design and document for inheritance or else prohibit it". (C'est l'article 17 de la deuxième édition et l'article 15 de la première édition. Tu devrais 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 être hérité de.
Classes doit donc venir en deux sortes :
-
Classes conçu pour être étendu , et avec suffisamment de documentation pour décrire comment il doit être fait
-
Classes marqué final
si vous écrivez un code purement interne, cela peut être un peu exagéré. Cependant, l'effort supplémentaire requis pour ajouter cinq caractères à un fichier de classe est très faible. Si vous n'écrivez que pour la consommation interne, alors un futur codeur peut toujours supprimer le "final" - vous pouvez penser à cela comme un avertissement disant "Cette classe n'a pas été conçue avec l'héritage à l'esprit".
vous pourriez vouloir rendre une méthode finale de sorte que les classes dominantes ne puissent pas changer le comportement qui est compté dans d'autres méthodes. Les méthodes appelées dans les constructeurs sont souvent déclarées finales afin que vous n'ayez pas de mauvaises surprises lors de la création d'objets.
une raison pour rendre une classe finale serait si vous vouliez forcer la composition sur l'héritage. Cela est généralement souhaitable pour éviter les couplages serrés entre classes.
vous pourriez vouloir faire des objets immuables ( http://en.wikipedia.org/wiki/Immutable_object ), vous pourriez vouloir créer un singleton ( http://en.wikipedia.org/wiki/Singleton_pattern ), ou vous pourriez vouloir empêcher quelqu'un d'outrepasser la méthode pour des raisons d'efficacité, de sécurité ou de sécurité.
il y a 3 cas d'utilisation où vous pouvez aller pour les méthodes finales.
- pour éviter que la classe dérivée ne supplante une fonctionnalité de classe de base particulière.
- C'est pour des raisons de sécurité, où la classe de base donne une fonctionnalité de base importante du framework où la classe dérivée n'est pas censée la changer.
- les méthodes finales sont plus rapides que les méthodes d'instance, car il n'y a pas d'utilisation de concept de table virtuelle 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 la fabrication d'une finale de classe:
pour qu'aucun corps ne puisse étendre ces classes et changer leur comportement.
Eg: Wrapper class entier est une classe finale. Si cette classe n'est pas finale, alors n'importe qui peut étendre entier dans sa propre classe et changer le comportement de base de classe integer. Pour éviter cela, java a créé toutes les classes wrapper comme classes finales.
L'héritage est comme une tronçonneuse-très puissant, mais terrible dans les mauvaises mains. Soit vous concevez une classe dont vous héritez (ce qui peut limiter la flexibilité et prendre beaucoup plus de temps), soit vous devriez l'interdire.
Voir Effective Java 2nd edition les articles 16 et 17, ou mon blog "droits de Succession" .
Hmmm... Je peux penser à deux choses:
vous pourriez avoir une classe qui traite de certaines questions de sécurité. En le sous-classant et en alimentant votre système la version sous-classifiée de celui-ci, un attaquant peut contourner les restrictions de sécurité. Par exemple: votre application pourrait prendre en charge des plugins et si un plugin peut simplement sous-classe vos classes de sécurité, il peut utiliser cette astuce pour faire passer une version subclassée de celui-ci en place. Cependant, C'est plutôt quelque chose que le soleil doit traiter concernant les applets et le genre, peut-être pas réaliste.
il est beaucoup plus réaliste d'éviter qu'un objet devienne mutable. Par exemple: puisque les chaînes sont immuables, votre code peut conserver en toute sécurité des références à lui
String blah = someOtherString;
au lieu de copier la chaîne. Cependant, si vous pouvez sous-classe String, vous pouvez y ajouter des méthodes qui permettent de modifier la valeur de la chaîne, maintenant aucun code ne peut plus compter que la chaîne restera la même si il copie simplement la chaîne comme ci-dessus, à la place il doit dupliquer la chaîne.
pour empêcher les gens de faire des choses qui pourraient les confondre avec les autres. Imaginez une bibliothèque de physique où vous avez des constantes définies ou des calculs. Sans utiliser le mot-clé final, quelqu'un pourrait venir et redéfinir des calculs de base ou des constantes qui ne devraient jamais changer.
en outre, si vous écrivez une classe de source fermé commercial, vous pourriez ne pas vouloir que les gens soient en mesure de changer la fonctionnalité vers le bas de la ligne, surtout si u besoin de donner du soutien pour elle et les gens ont dépassé votre méthode et se plaignent que l'appel il donne des résultats inattendus.
si vous marquez les classes et les méthodes comme finales, vous pouvez remarquer un petit gain de performance, puisque l'exécution n'a pas à rechercher la bonne méthode de classe à invoquer pour un objet donné. Les méthodes Non-finales sont marquées comme virtuelles afin qu'elles puissent être correctement étendues si nécessaire, les méthodes finales peuvent être directement liées ou compilées en ligne dans la classe.
vous voulez rendre une méthode finale pour que les classes dominantes ne changent pas son comportement. Quand vous voulez être en mesure de changer le comportement rendre la méthode publique. Lorsque vous outrepassez une méthode publique, elle peut être modifiée.