Question

Pourquoi quelqu'un voudrait-il marquer une classe comme définitive ou scellé?

Était-ce utile?

La solution

Selon Wikipedia , « les classes Sealed sont principalement utilisés pour prévenir dérivation. Ils ajoutent un autre niveau de compilation lors de la rigueur du temps, améliorer l'utilisation de la mémoire, et de déclencher certaines optimisations qui améliorent l'efficacité de l'exécution. "

En outre, à partir de le blog de Patrick Smacchia :

  
      
  • Versioning: Lorsqu'une classe est à l'origine scellé, il peut changer de descellé à l'avenir sans compatibilité briser. (...)

  •   
  • Performance:. (...) si le compilateur JIT voit un appel à une méthode virtuelle en utilisant un type scellé, le compilateur JIT peut produire un code plus efficace en appelant non pratiquement la méthode (...)

  •   
  • Sécurité et Prévisibilité: Une classe doit protéger son propre état et ne se laissera jamais devenir corrompu. Lorsqu'une classe est descellé, une classe dérivée peut accéder et manipuler l'état de la classe de base si les champs de données ou méthodes qui manipulent en interne les champs sont accessibles et non privés. (...)

  •   

Ce sont toutes assez bonnes raisons - En fait, je ne savais pas que des répercussions des prestations de performance jusqu'à ce que je l'ai regardé jusqu'à ce moment:)

Les versioning et les points de sécurité semblent comme un énorme avantage en termes de confiance de code, ce qui est très bien justifiée sur tout type de grand projet. Il n'y a pas pour les tests unitaires en baisse, bien sûr, mais il serait utile.

Autres conseils

Parce que la création d'un type d'héritage est beaucoup plus difficile travail que la plupart des gens pensent. Il est préférable de marquer tous types de cette façon par défaut, car cela empêche que d'autres héritant d'un type qui n'a jamais été destiné à être étendu.

Si oui ou non un type devrait être étendue est une décision du développeur qui l'a créé, pas le développeur qui vient plus tard et veut l'étendre.

Joshua Bloch dans son livre Effective Java parle. Il dit « document pour l'héritage ou la désavouer ». Le point est que la classe est en quelque sorte d'un contrat entre l'auteur et le client. Permettre client d'hériter de la classe de base rend ce contrat beaucoup plus stricte. Si vous allez hériter de lui, vous avez probablement allez passer outre certaines méthodes, sinon vous pouvez remplacer l'héritage avec la composition. Quelles méthodes sont autorisées à être surchargée, et ce que vous avez à faire leur mise en œuvre - devraient être documentées ou votre code peut conduire à des résultats imprévisibles. Pour autant que je me souviens, il montre comme exemple - voici une classe de collection avec des méthodes

public interface Collection<E> extends Iterable<E> {    
  ...
  boolean add(E e);
  boolean addAll(Collection<? extends E> c);
  ...
}

Il y a une mise en œuvre, à savoir ArrayList. Maintenant, vous voulez hériter de et remplacer certaines méthodes, il imprime sur la console un message lorsque l'élément est ajouté. Maintenant, avez-vous besoin de passer outre à la fois Ajouter et addAll , ou seulement Ajouter ? Cela dépend de la façon dont addAll est mis en œuvre - directement t-il avec l'état interne (comme le fait ArrayList) ou appelle Ajouter (comme le fait AbstractCollection). Ou peut-être il y a addInternal , qui est appelé à la fois par ajouter et addAll . Il n'y avait pas de telles questions jusqu'à ce que vous avez décidé d'hériter de cette classe. Si vous utilisez juste - ça ne vous dérange pas. Ainsi, l'auteur de la classe doit documenter, s'il veut que vous hériter de sa classe.

Et s'il veut changer la mise en œuvre à l'avenir? Si sa classe est utilisé, jamais hérité de, rien ne l'empêche de changer la mise en œuvre plus efficace. Maintenant, si vous avez hérité de cette classe, regardé à la source et a constaté que addAll add , vous remplacez seulement Ajouter . Plus tard l'auteur change donc la mise en œuvre addAll n'appelle plus ajouter - votre programme est cassé, le message n'est pas imprimé lorsque addAll est appelé. Ou vous avez regardé à la source et a constaté que addAll ne remet pas ajouter, si vous remplacez ajouter et addAll . Maintenant auteur change la mise en œuvre, de sorte que addAll Appels ajouter -. Votre programme est brisé à nouveau, lorsque l'on appelle addAll message est imprimé deux fois pour chaque élément

- si vous voulez que votre classe soit héritée de, vous avez besoin de documenter comment. Si vous pensez que vous devrez peut-être changer quelque chose dans l'avenir qui peut briser certaines sous-classes - vous devez penser comment l'éviter. En laissant vos clients héritent de votre classe, vous exposez beaucoup plus de détails d'implémentation interne que vous faites lorsque vous laissez juste les utiliser votre classe - vous exposiez flux de travail interne, qui est souvent soumis à des changements dans les futures versions.

Si vous exposez quelques détails et les clients Invocabilité - vous ne pouvez plus les changer. Si elle est ok avec vous, ou vous documenté ce qui peut et ce qui ne peut être outrepassée - c'est très bien. Parfois, vous ne voulez pas. Parfois, vous voulez juste dire -. « Il suffit d'utiliser cette classe, jamais hériter de lui, parce que je veux une liberté de modifier les détails d'implémentation interne »

Donc, fondamentalement commenter « Parce que la classe ne veut pas avoir d'enfants et nous devons respecter ses souhaits » est correct.

Alors, quelqu'un veut marquer une classe comme finale / scellé, quand il pense que les détails possibles de mise en œuvre des changements sont plus précieux que l'héritage. Il existe d'autres façons d'obtenir des résultats similaires à l'héritage.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top