web-dev-qa-db-fra.com

Pourquoi utiliser «final» sur une classe est-il vraiment si mauvais?

Je refactorise un site Web hérité PHP OOP).

Je suis tellement tenté de commencer à utiliser "final" sur les classes pour "make it explicit that the class is currently not extended by anything ". Cela pourrait faire gagner beaucoup de temps si je viens à une classe et je me demande si je peux renommer/supprimer/modifier une propriété ou une méthode protected. Si je vraiment je veux pour étendre une classe, je peux simplement supprimer le mot-clé final pour déverrouiller pour étendre.

Si je viens dans une classe qui n'a pas de classes enfants, je peux enregistrer ces connaissances en marquant la classe comme finale. La prochaine fois que j'y viendrai, je n'aurais pas à rechercher à nouveau la base de code pour voir si elle a des enfants. Gain de temps lors des refactorisations.

Tout cela semble être une idée raisonnable pour gagner du temps ... mais j'ai souvent lu que les cours ne devraient être rendus "finaux" que dans des occasions rares/spéciales.

Peut-être que cela gâche la création d'objets Mock ou a d'autres effets secondaires auxquels je ne pense pas.

Qu'est-ce que je rate?

34
JW01

J'ai souvent lu que les cours ne devraient être "finaux" que dans des occasions rares/spéciales.

Celui qui a écrit cela est faux. Utilisez final généreusement, il n'y a rien de mal à cela. Il documente qu'une classe n'a pas été conçue avec l'héritage à l'esprit, et cela est généralement vrai pour toutes les classes par défaut: la conception d'une classe qui peut être héritée de manière significative prend plus que la simple suppression d'un spécificateur final; cela demande beaucoup de soin.

Donc, utiliser final par défaut n'est pas mauvais du tout. En fait, beaucoup de gens proposent que ce soit la valeur par défaut, par exemple Jon Skeet .

Peut-être que ça fout la création d'objets Mock…

C'est en effet une mise en garde, mais vous pouvez toujours recourir à des interfaces si vous avez besoin de vous moquer de vos classes. C'est certainement supérieur à rendre toutes les classes ouvertes à l'héritage uniquement à des fins de moquerie.

54
Konrad Rudolph

Si vous voulez vous laisser une note qu'une classe n'a pas de sous-classes, alors faites-le et utilisez un commentaire, c'est à ça qu'elles servent. Le mot-clé "final" n'est pas un commentaire, et utiliser des mots-clés de langue juste pour vous signaler quelque chose (et vous seul saurez ce que cela signifie) est une mauvaise idée.

8
Jeremy

Il y a un bel article sur "Quand déclarer les classes finales" . Quelques citations:

TL; DR: faites toujours vos classes final, si elles implémentent une interface, et qu'aucune autre méthode publique n'est définie

Pourquoi dois-je utiliser final?

  1. Empêcher la chaîne d'héritage massive de Doom
  2. Composition encourageante
  3. Forcer le développeur à penser à l'API publique des utilisateurs
  4. Forcer le développeur à réduire l'API publique d'un objet
  5. Une classe final peut toujours être rendue extensible
  6. extends interrompt l'encapsulation
  7. Vous n'avez pas besoin de cette flexibilité
  8. Vous êtes libre de changer le code

Quand éviter final:

Les classes finales ne fonctionnent efficacement que sous les hypothèses suivantes:

  1. Il existe une abstraction (interface) que la classe finale implémente
  2. Toute l'API publique de la classe finale fait partie de cette interface

Si l'une de ces deux conditions préalables est manquante, vous atteindrez probablement un moment où vous rendrez la classe extensible, car votre code ne s'appuie pas vraiment sur des abstractions.

P.S. Merci à @ocramius pour cette excellente lecture!

5
Nikita U.

"final" pour une classe signifie: Vous voulez une sous-classe? Allez-y, supprimez la sous-classe "finale" autant que vous le souhaitez, mais ne me plaignez pas si cela ne fonctionne pas. Tu es tout seul.

Lorsqu'une classe peut être sous-classée, c'est le comportement sur lequel les autres comptent, doit être décrit en termes abstraits auxquels les sous-classes obéissent. Les appelants doivent être écrits pour s'attendre à une certaine variabilité. La documentation doit être rédigée avec soin; vous ne pouvez pas dire aux gens de "regarder le code source" car le code source n'est pas encore là. C'est tout l'effort. Si je ne m'attends pas à ce qu'une classe soit sous-classée, c'est un effort inutile. "final" indique clairement que cet effort n'a pas été fait et donne un avertissement juste.

5
gnasher729