Comment la conception pour l'héritage peut-elle entraîner des coûts supplémentaires? [fermé]

12

J'ai donc voulu hériter d'un sealed classdans csharp et j'ai été brûlé. Il n'y a tout simplement aucun moyen de le desceller à moins d'avoir accès à la source.

Ensuite, cela m'a fait penser "pourquoi sealedexiste-t-il même?". Il ya 4 mois. Je n'ai pas pu le comprendre, malgré la lecture de beaucoup de choses à ce sujet, telles que:

J'ai essayé de digérer tout cela depuis, mais c'est trop pour moi. Finalement, hier, je l'ai essayé à nouveau. Je les ai à nouveau analysés, et quelques autres:

Enfin, après beaucoup de réflexion, j'ai décidé de modifier fortement la question d'origine en fonction du nouveau titre.

La vieille question était trop large et subjective. Il s'agissait essentiellement de demander:

  1. Dans l'ancien titre: une bonne raison d'utiliser scellé
  2. Dans le corps: comment modifier correctement une classe scellée? Oubliez l'héritage? Utiliser la composition?

Mais maintenant, en comprenant (ce que je n'ai pas fait hier) que tout sealedfait empêche l'héritage , et nous pouvons et devons en effet utiliser la composition plutôt que l'héritage , j'ai réalisé que j'avais besoin d' exemples pratiques .

Je suppose que ma question ici est (et en fait a toujours été) exactement ce que M. Mindor m'a suggéré dans une conversation : comment la conception pour l'héritage peut-elle entraîner des coûts supplémentaires?

cregox
la source
5
La question est formulée de manière assez agressive et sonne comme une diatribe. Vous devriez le reformuler si vous voulez des réponses pertinentes et objectives.
Euphoric
11
Voir Pourquoi tant de classes de framework sont-elles scellées? par Eric Lippert. Il fournit plusieurs bonnes raisons de sceller des cours.
Robert Harvey
9
Ensuite, vous n'avez pas lu l'article. Revenez en arrière et relisez-le. Cela se résume à ceci: vous ne pouvez pas prédire les innombrables façons dont un client pourrait casser votre classe en l'étendant. Vous pouvez blâmer vos clients pour cela, mais c'est vous qui devrez les soutenir.
Robert Harvey
4
@Cawas Il pourrait, ou vous pourriez lire l'article qu'il a lié qui l'explique en détail. Il résumait simplement cet article avec son commentaire.
Servy
7
Désolé, mais je ne suis pas celui qui se déchaîne ici. La réponse à votre question est très simple: scellez une classe lorsque vous ne voulez pas prendre en charge l'héritage. C'est ça.
Robert Harvey

Réponses:

27

Ce n'est pas si difficile à comprendre. sealeda été créé SPÉCIFIQUEMENT pour Microsoft afin de leur faciliter la vie, d'économiser des tonnes d'argent et d'améliorer leur réputation. Puisqu'il s'agit d'une fonction de langue, tout le monde peut également l'utiliser, mais VOUS n'aurez probablement jamais besoin d'utiliser scellé.

La plupart des gens se plaignent de ne pas pouvoir étendre une classe et s'ils le font, ils disent que tout le monde sait que c'est la responsabilité des développeurs de la faire fonctionner correctement. C'est vrai, SAUF que ces mêmes personnes n'ont aucune idée de l'histoire de Windows et l'un des problèmes sealedessaie de résoudre.

Supposons qu'un développeur ait étendu une classe de base .Net (car scellé n'existait pas) et l'a fait fonctionner parfaitement. Oui, pour le développeur. Le développeur livre le produit au client. L'application du développeur fonctionne très bien. Le client est content. La vie est belle.

Désormais, Microsoft publie un nouveau système d'exploitation, qui comprend la correction des bogues dans cette classe de base .Net particulière. Le client souhaite suivre son temps et choisit d'installer le nouveau système d'exploitation. Du coup, l'application que le client aime tant ne fonctionne plus, car elle ne tenait pas compte des bugs corrigés dans la classe de base .Net.

Qui en est responsable?

Ceux qui connaissent l'histoire de Microsoft savent que le nouveau système d'exploitation de Microsoft sera blâmé et non le logiciel d'application qui a mal utilisé les bibliothèques Windows. Il revient donc à Microsoft de résoudre le problème au lieu de la société d'application qui a créé le problème. C'est l'une des raisons pour lesquelles le code Windows s'est gonflé. D'après ce que j'ai lu, le code du système d'exploitation Windows est jonché de if-then spécifique pour vérifier si une application et une version spécifiques sont en cours d'exécution et si oui, effectuez un traitement spécial pour permettre au programme de fonctionner. C'est beaucoup d'argent dépensé par Microsoft pour corriger l'incompétence d'une autre entreprise.

L'utilisation sealedn'élimine pas complètement le scénario ci-dessus, mais cela aide.

Tremper
la source
4
@Cawas Il est assez difficile d'en abuser. Eric Lippert a déclaré à plusieurs reprises qu'il souhaitait que les classes, comme les méthodes, soient toutes sealedpar défaut, sauf si elles étaient spécifiquement scellées, simplement parce que si peu de classes sont réellement conçues pour être héritées. Il est beaucoup plus probable que votre classe n'ait pas été conçue pour la prendre en charge, et vous devez vous assurer que vous avez passé ce temps de développement si vous vous efforcez de la marquer comme non scellée.
Servy
1
Je pense que si les gens utilisent le scellé pour leur logiciel de développement interne, ils l'utilisent probablement mal ou perdent simplement du temps de l'entreprise à essayer d'être trop parfait. Je dis probablement parce qu'il y a toujours des cas où l'on peut trouver cela logique dans un scénario particulier. Cependant, pour ceux qui développent un logiciel de type bibliothèque, je soupçonne qu'il est très utile pour les mêmes raisons que Microsoft a décidé qu'il était nécessaire.
Dunk
2
@Cawas La grande majorité des classes écrites par la plupart des développeurs n'auront jamais besoin d'être héritées et ne sont pas écrites pour prendre en charge l'héritage. Cela peut être transmis rapidement et efficacement aux lecteurs / utilisateurs du code en faisant le type sealed. S'il s'agissait en fait de l'option par défaut, cela signifierait que si quelqu'un héritait d'un type, il saurait qu'il est conçu pour le prendre en charge.
Servy
2
Le descellement d'une classe ne signifierait pas que la classe a été conçue pour la prendre en charge. Cela signifie simplement que quelqu'un a voulu hériter de la classe et l'a descellée. Dans le meilleur des cas, l'utilisation de scellé obligera simplement les développeurs à réécrire les fonctionnalités existantes (équivalentes à la classe scellée), mais le plus souvent, si le code source est disponible, ils le descelleront simplement sans prendre en compte les conséquences. Après avoir scellé être spécifiquement et rarement défini, c'est mieux car le développeur pourrait alors vouloir comprendre pourquoi cette classe est scellée. Trop de classes scellées et ils ne se soucieront pas pourquoi.
Dunk
1
La sécurité est également une raison de l'utiliser! Imaginez une application en bac à sable essayant d'accéder à un fichier. Le bac à sable peut tester les chaînes de nom de fichier, mais que se passe-t-il si un attaquant peut vous envoyer un fichier mutable String puis le muter après le contrôle de sécurité mais avant les E / S? Je crois que ce type de scénario est la raison pour laquelle Java Stringest marqué final(similaire à sealed) et je parie que la même logique sous-tend certaines décisions C #.
Darien
23

sealedest utilisé pour indiquer que l'auteur de la classe ne l'a pas conçu pour être hérité. Rien de moins, rien de plus.

Concevoir correctement une interface est déjà assez difficile pour de nombreux programmeurs. Concevoir correctement une classe qui peut être potentiellement héritée ajoute de la difficulté et des lignes de code. Plus de lignes de code écrites signifient plus de code à maintenir. Pour éviter cette difficulté croissante, sealedpeut montrer que la classe n'a jamais été destinée à être héritée, et dans ce contexte, sceller une classe est une solution parfaitement valide à un problème .

Imaginez le cas d'où CustomBoeing787dérive la classe Airliner. Cela CustomBoeing787remplace certaines méthodes protégées de Airliner, mais pas toutes. Si le développeur a suffisamment de temps et que cela en vaut la peine, il peut tester la classe à l'unité pour s'assurer que tout fonctionne comme prévu, même dans un contexte où des méthodes non remplacées sont appelées (par exemple, des setters protégés qui changent l'état de l'objet). Si le même développeur (1) n'a pas le temps, (2) ne veut pas dépenser des centaines ou des milliers de dollars supplémentaires de son patron / client, ou (3) ne veut pas écrire de code supplémentaire, il ne le fait pas besoin en ce moment (YAGNI), alors il peut:

  • soit libérer le code dans la nature tel quel, étant donné que c'est la préoccupation des programmeurs qui maintiendront ce projet plus tard pour se soucier des bugs potentiels,

  • ou marquez la classe sealedpour montrer explicitement aux futurs programmeurs que cette classe n'est pas destinée à être héritée, et que la descellage et son utilisation en tant que parent doivent se faire à vos propres risques.

Est-ce une bonne idée de sceller autant de classes que possible, ou aussi peu que possible? D'après mon expérience, il n'y a pas de réponse définitive. Certains développeurs ont tendance à en utiliser sealedtrop; d'autres ne se soucient pas de la façon dont la classe serait héritée et du problème qu'elle pourrait causer. Face à une telle utilisation, le problème est similaire à celui qui consiste à déterminer si les programmeurs doivent utiliser deux ou quatre espaces pour l'indentation: il n'y a pas de bonne réponse.

Arseni Mourzenko
la source
Très bien ... Désolé si je semble à nouveau agressif, mais je veux juste être clair et affirmé ici ... Je ne peux comprendre ce que vous venez d'écrire que de deux manières, si vous deviez en écrire un tl;drici. C'est soit "Non, il n'y a pas une seule bonne raison" , soit "Je pense qu'il n'y a pas de bonne raison, mais je ne sais pas aussi bien". . Pour moi, "pas de réponse définitive" est l'un ou l'autre.
cregox
6
sealedest utilisé pour indiquer que l'auteur de la classe ne l'a pas conçu pour être hérité. Voilà votre seule bonne raison.
Robert Harvey
C'est aussi une bonne raison que de vous donner un vélo sans lumières et de forcer, d'une manière ou d'une autre, vous ne pouvez pas ajouter de lumières.
cregox
2
@Cawas Comment ça? Dans ce contexte, il n'est pas important pour le constructeur de vélos de s'assurer que le vélo n'a pas de lumière, mais il est souvent important pour l'utilisateur d'un type de s'assurer que la mise en œuvre est une mise en œuvre exacte particulière. Vous imposez les contraintes dont vous avez besoin. Dans certains cas, les gens peuvent ajouter une contrainte qui n'est pas réellement nécessaire; vous en avez donné un exemple. Ce n'est pas parce que la contrainte est mal utilisée à un seul endroit que vous ne devez jamais contraindre quoi que ce soit.
Servy
1
La sécurité est également une raison de l'utiliser! Imaginez une application en bac à sable essayant d'accéder à un fichier. Le bac à sable peut tester les chaînes de nom de fichier, mais que se passe-t-il si un attaquant peut vous envoyer un fichier mutable String puis le muter après le contrôle de sécurité mais avant les E / S? Je crois que ce type de scénario est la raison pour laquelle Java Stringest marqué final(similaire à sealed) et je parie que la même logique sous-tend certaines décisions C #.
Darien
4

Lorsqu'une classe est scellée, elle permet au code utilisant ce type de savoir exactement à quoi elles ont affaire.

Maintenant , en C # stringest sealed, vous ne pouvez pas en hériter, mais supposons une seconde que cela n'a pas été le cas. Si vous l'avez fait, alors quelqu'un pourrait écrire un cours comme celui-ci:

public class EvilString// : String
{
    public override string ToString()
    {
        throw new Exception("I'm mean");
    }
    public override bool Equals(object obj)
    {
        return false;
    }
    public override int GetHashCode()
    {
        return 0;
    }
}

Ce serait maintenant une classe de chaînes qui viole toutes sortes de propriétés que les concepteurs stringsavaient être vraies. Ils savaient que la Equalsméthode serait transitive, ce n'est pas le cas. Heck, cette méthode égale n'est même pas symétrique, car une chaîne pourrait être égale à elle, mais elle ne serait pas égale à cette chaîne. Je suis sûr qu'il y a toutes sortes de programmeurs qui ont écrit du code en supposant que la ToStringméthode de stringne lèvera pas d'exception pour les valeurs non nulles. Vous pourrez désormais violer cette hypothèse.

Il existe un certain nombre d'autres classes pour lesquelles nous pourrions le faire, et toutes sortes d'autres hypothèses que nous pourrions violer. Si vous supprimez la fonction de langue poursealedles concepteurs de langage doivent maintenant commencer à tenir compte de ce genre de choses dans tout le code de leur bibliothèque. Ils doivent effectuer toutes sortes de vérifications pour s'assurer que les types étendus des types qu'ils souhaitent utiliser seront écrits "correctement", ce qui peut être une opération très coûteuse (à la fois en temps de développement et au moment de l'exécution). En étant en mesure de sceller une classe, ils peuvent garantir que cela n'est pas possible et que toutes les affirmations qu'ils font sur les détails d'implémentation de leurs propres types ne peuvent pas être violées, à l'exception des types qui sont intentionnellement conçus pour être étendus. Pour ces types conçus pour être étendus, vous trouverez que le code de langue doit être beaucoup plus défensif sur la façon dont il les traite.

Servy
la source
Mais vous pouvez violer cette hypothèse dans votre code . Ce n'est pas comme si vous preniez la source de String et la modifiiez. Les concepteurs n'auraient pas besoin de tenir compte de cela car c'est 1 feuille, 1 branche, 1 client qui l'utilise à ses propres risques et discrétion. Il ne sera pas diffusé à partir de là, sauf si d'autres clients préfèrent le faire. Etc.
cregox
3
@Cawas Et si une exception est levée à un moment inattendu et qu'une ressource est perdue en conséquence, ou qu'une classe est laissée dans un état indéterminé et fonctionne de manière inappropriée? Ce cas est un peu idiot, mais il pourrait facilement arriver que quelqu'un écrive une implémentation qu'il pense raisonnable, mais jette parfois quand cela ne devrait pas, ou ne fonctionne pas avec certaines valeurs. Ils se plaindront alors lorsque le code de langue ne fonctionnera pas. Il est préférable de ne pas laisser les gens faire des choses que la langue ne pourra pas supporter.
Servy
Dans tous les cas, vous parlez de construire un compilateur. Il existe de nombreuses sealedfonctionnalités intégrées qui ne sont pas exposées pour nous. Il n'explique toujours pas pourquoi l'utiliser en dehors d'une portée aussi étroite et, étant aussi étroit que le code du compilateur , n'explique même pas l' sealedexistence.
cregox
2
@Cawas Le stringtype n'est pas du code de compilation. Cela fait partie du code de langue. Complètement différent. En tout cas, je viens de choisir un exemple. Vous pouvez choisir la plupart des classes scellées de la BCL entière et l'utiliser comme exemple.
Servy
4
@Cawas: Je pense que ce qui pourrait vous manquer ici, c'est l'aspect du support client. Si vous autorisez une classe à être héritable, les clients en hériteront, puis ils vous appelleront lorsqu'elle se cassera. Vous pouvez leur dire toute la journée qu'ils héritent de cette classe à leurs risques et périls, mais vous allez toujours recevoir l'appel, car vous leur avez permis d' hériter de cette classe , alors ils supposent qu'il est sûr de le faire.
Robert Harvey
3

Y a-t-il une bonne raison d'utiliser scellé?

Ah non? Pas souvent. Je n'utilisé scellé quand j'ai un type immuable (ou une autre limitation) qui vraiment vraiment doit rester immuable et je ne peux faire confiance à furfill que héritières exigence sans introduire des bugs subtils, catastropic dans le système.

Supposons qu'il y ait une bonne raison d'utiliser scellé et que nous devrions l'utiliser par défaut pour tout, que faisons-nous avec l'héritage?

Nous utilisons l'héritage pour les choses qui ne sont pas par défaut. Même si la composition est préférée à l'héritage (et c'est le cas), cela ne signifie pas que l'héritage doit être rejeté. Cela signifie que l'héritage a certains problèmes intrinsèques qu'il introduit dans la conception et la maintenabilité du code et que la composition fait la même chose avec (en général) moins de problèmes. Et cela signifie que même si la composition est privilégiée, l'hérédité est bonne pour certains sous-ensembles de problèmes.

Je ne veux pas être trop méchant, mais si vous venez d'entendre parler de SOLID et des tests unitaires, peut-être devriez-vous sortir de votre sous-pierre et écrire du code. Les choses ne sont pas claires, et rarement "toujours faire X" ou "ne jamais utiliser Y" ou "Z est le meilleur" soit la bonne façon (comme il semble que vous gravitez vers en fonction des vues de votre question). Lorsque vous écrivez du code, vous pouvez voir des cas où cela sealedpourrait être bon et des cas où cela vous cause du chagrin - comme tout autre compromis.

Telastyn
la source
Pour moi, ceci et le "pour éviter d'avoir à supporter l'héritage des clients" que Robert ne veut pas élaborer sont les réponses les plus prometteuses ... Peut-être pourriez-vous en dire plus sur les cas où vous les utilisez sealed, s'il vous plaît?
cregox
@Cawas - Je ne suis pas sûr de pouvoir le faire. Je le fais très rarement, et c'est souvent un compromis où la garantie que quelque chose reste immuable (pour optimiser les performances, simplifier la conception) vaut l'incapacité d'hériter de l'objet.
Telastyn
C'est super. Dunk l'a déjà trempé! : P Merci beaucoup pour la réponse. Et vous étiez le seul à avoir mes "subtils indices" sur mon expertise. On dirait que les gens supposaient que j'en savais plus, je ne sais pas ... Mais je souhaite que "juste le codage" me fasse sortir de ce rocher. Peut-être que j'applique ces concepts d'une manière ou d'une autre, mais pas aussi procéduralement que je le devrais probablement.
cregox
3

Tout d'abord, vous devriez lire le post d'Eric Lippert sur les raisons pour lesquelles Microsoft scelle ses classes.

http://blogs.msdn.com/b/ericlippert/archive/2004/01/22/61803.aspx

Deuxièmement, le mot clé scellé existe pour faire exactement ce qu'il fait - empêcher l'héritage. Il existe de nombreuses situations où vous souhaitez empêcher l'héritage. Considérez une classe dont vous avez une collection. Si votre code dépend du fait que cette classe fonctionne d'une manière particulière, vous ne voulez pas que quelqu'un remplace une des méthodes ou propriétés de cette classe et provoque l'échec de votre application.

Troisièmement, l'utilisation de scellés encourage la composition plutôt que l'héritage, ce qui est une bonne habitude. L'utilisation de la composition sur l'héritage signifie que vous ne pouvez pas briser le principe de substitution de Liskov et que vous suivez le principe Open / Closed. sealedest donc un mot-clé qui vous aide à suivre deux des cinq principes les plus importants de la programmation oo. Je dirais que cela en fait une fonctionnalité très précieuse.

Stephen
la source
La première partie est déjà soulignée dans les commentaires de la question. La deuxième partie est juste plus de raisonnement sans véritables causes. La troisième partie, même si elle a déjà été abordée ailleurs, pourrait avoir quelque chose à y voir. Je me concentrerais sur celui-là.
cregox
le troisième point n'encourage pas la composition plutôt que l'héritage, il élimine complètement l'héritage en option, même si c'était le meilleur choix global.
Michael Shaw
Cela dépend si vous contrôlez la base de code ou non. Si vous scellez des classes, vous pouvez toujours les desceller plus tard si nécessaire.
Stephen
2

Je pense que cette question n'a pas de réponse objective et que tout dépend de votre point de vue.

D'un côté, certaines personnes veulent que tout soit «ouvert» et le fardeau de s'assurer que tout fonctionne correctement incombe à la personne qui prolonge la classe. C'est pourquoi les classes sont ouvertes à l'héritage par défaut. Et pourquoi les méthodes Java sont toutes virtuelles par défaut.

De l'autre côté, certains veulent que tout soit fermé par défaut et offrent des options pour l'ouvrir. Dans ce cas, c'est l'auteur de la classe de base qui doit s'assurer que tout ce qu'il "ouvre" est sûr à utiliser de n'importe quelle manière imaginable. C'est pourquoi en C # toutes les méthodes sont non virtuelles par défaut et doivent être déclarées virtuelles pour être remplacées. C'est aussi pour ces personnes, qui doivent être un moyen de contourner les défauts «ouverts». Comme rendre la classe scellée / finale, car ils voient quelqu'un dérivant de la classe un gros problème pour la conception de leur propre classe.

Euphorique
la source
C'est plus comme ça! Cela pourrait être une bonne raison ... "Parce que les gens veulent le fermer". Et c'est aussi ce que j'essaie de dire dans la question: on dirait que les classes non virtuelles en C ++ peuvent être remplacées. sealedne peut pas. Comment en hériter? Tout ce que je lis, c'est que nous ne pouvons pas. Déjà. Je ne sais pas. Je fais des allers-retours sur ce sujet depuis 4 mois maintenant, depuis que j'ai entendu parler de scellé pour la première fois. Et je ne sais toujours pas comment le faire correctement quand j'ai besoin de modifier quoi que ce soit sur une classe scellée. Donc, je ne vois aucune "option pour l'ouvrir"!
cregox
4
Ce n'est pas pourquoi les méthodes de classe C ++ ne sont pas virtuelles par défaut. Rendre une méthode virtuelle signifie qu'il doit y avoir des frais supplémentaires sur la table de recherche de méthode, et C ++ a la philosophie que vous ne payez pour les frais généraux que lorsque vous voulez la fonctionnalité.
Michael Shaw
@Ptolemy Ok, je l'ai supprimé. Je n'aurais jamais dû l'écrire, car je savais que les gens commençaient à s'en plaindre.
Euphoric
Hé, j'apprécie complètement que si vous voulez prétendre que les gens veulent écrire des cours fermés par défaut, et doivent choisir activement de les ouvrir, alors vous allez devoir vous accrocher à des pailles
Michael Shaw
L'OMI est extrêmement similaire aux débats privés / protégés / publics en ce qui concerne les API: cela dépend fortement de qui contrôle la classe, qui veut hériter de la classe, de la communication entre les deux et de la fréquence à laquelle de nouvelles versions sortent.
Darien
-2

le problème avec scellé en C # est que c'est plutôt final. En 7 ans de développement commercial C #, le seul endroit où je l'ai vu utilisé est sur les classes Microsoft .NET où je pense que j'avais une raison légitime d'étendre une classe de framework pour implémenter un comportement ajusté, et parce que la classe était scellée, je ne pouvais pas .

Il est impossible d'écrire une classe en pensant à toutes les façons possibles de l'utiliser et en décidant qu'aucune d'entre elles n'est légitime. De même, si la sécurité du framework dépend de l'héritage de la classe, vous avez un défaut de conception de sécurité.

Donc, en conclusion, je suis fermement d'avis que le scellé ne sert à rien, et rien de ce que j'ai lu jusqu'ici n'a changé ce point de vue.

Je peux voir qu'il y a eu jusqu'à présent trois arguments qui justifient la mise sous scellés jusqu'à présent.

  1. L'argument 1 est qu'il élimine une source de bogues lorsque les gens héritent des classes et ont ensuite un accès accru aux internes de cette classe sans vraiment comprendre correctement les internes.

  2. L'argument 2 est que si vous étendez une classe microsoft, puis que microsoft implémente un correctif de bogue dans cette classe mais que votre extension reposait sur ce bogue, votre code est maintenant cassé, microsoft obtient le blâme et scellé empêche cela

  3. L'argument 3 est qu'en tant que développeur de la classe, c'est mon choix de vous autoriser ou non à l'étendre, dans le cadre de ma conception de la classe.

L'argument 1 semble être un argument selon lequel vous, le programmeur final, ne savez pas comment utiliser mon code. C'est peut-être le cas, mais si vous me permettez toujours d'accéder à l'interface des objets, il est toujours vrai que j'utilise votre objet et que je l'appelle sans comprendre comment l'utiliser, et peut donc faire autant de dégâts de cette façon . Il s'agit d'une faible justification de la nécessité de scellé.

Je comprends d'où vient la base factuelle de l'argument 2. En particulier, lorsque Microsoft a effectué des vérifications supplémentaires du système d'exploitation sur les appels d'API Win32 pour identifier les appels mal formés, qui ont amélioré la stabilité générale de Windows XP par rapport à Windows NT, mais au coût à court terme, de nombreuses applications ont été cassées lors de la sortie de Windows XP. Microsoft a résolu ce problème en ajoutant des «règles» pour ces vérifications, à savoir ignorer lorsque l'application X enfreint cette règle, c'est un bogue connu

L'argument 2 est un argument médiocre, car scellé au mieux ne fait pratiquement aucune différence, car s'il y a un bogue dans la bibliothèque .NET, vous n'avez pas d'autre choix que de trouver un moyen de contourner le problème et lorsque le correctif Microsoft sortira, il est fort probable signifie que votre travail qui dépend du comportement rompu est maintenant rompu. Que vous ayez contourné cela en utilisant l'héritage ou par un autre code wrapper supplémentaire, lorsque le code est corrigé, votre travail sera interrompu.

L'argument 3 est le seul argument qui ait une substance pour se justifier. Mais c'est encore faible. Cela va à l'encontre de la réutilisation du code.

Michael Shaw
la source
2
/ moi envoie un e-mail à Microsoft, pouvez-vous desceller la classe X pour moi et expédier une nouvelle version de .NET. Cordialement, .... Comme je l'ai dit, la seule fois dans le développement commercial que j'ai vu une classe scellée, il n'a pas été possible de la desceller.
Michael Shaw
6
It is impossible to write a class thinking about every possible way it could be used- C'est précisément la raison pour laquelle de nombreuses classes Framework sont scellées ... Cela élimine la nécessité de réfléchir à toutes les manières possibles d'étendre la classe.
Robert Harvey
5
Si vous pouviez le desceller, il ne servirait à rien de le sceller, n'est-ce pas?
Robert Harvey
2
@Ptolemy Permettre aux gens d'étendre votre classe est une fonctionnalité . Celui qui consomme une quantité importante d'efforts de développement. C'est une fonctionnalité qui ne mérite d'être justifiée que si l'auteur de la classe peut voir suffisamment d'avantages dans les extensions potentielles pour justifier l'effort. S'ils ne peuvent pas justifier l'effort, et donc que le type et ses utilisateurs ne sont pas conçus pour prendre en charge l'extension, il est important de l'empêcher, sinon vous seriez techniquement en mesure d'étendre le type, mais il est peu probable qu'il fonctionne correctement lorsque vous le faites.
Servy
2
@Cawas: Vous êtes juste difficile.
Robert Harvey
-7

J'utilise uniquement des sealedmots clés sur les classes qui ne contiennent que des méthodes statiques.

Vladimir Kocjancic
la source
9
Alors pourquoi ne pas simplement marquer la classe comme étant à la staticplace?
Servy
@Servy ... Bon point.
Vladimir Kocjancic
-8

Comme le montre ma question, je ne suis pas un expert ici. Mais je ne vois aucune raison sealedd'exister.

Il semble être fait pour aider les architectes de code à concevoir une interface. Si vous voulez écrire une classe qui sortira dans la nature et que beaucoup de gens en hériteront, modifier quoi que ce soit dans cette classe peut la casser pour trop de gens. Nous pouvons donc le sceller et personne ne peut hériter. "Problème résolu".

Eh bien, cela ressemble à "couvrir un endroit et en découvrir un autre". Et ce n'est même pas la résolution d'un problème - c'est simplement l' élimination d'un outil : l' héritage. Comme tout outil, il a de nombreux usages et hériter d'une classe instable est un risque que vous prenez. Celui qui a pris ce risque devrait mieux le savoir.

Peut-être qu'il pourrait y avoir un mot-clé stable, afin que les gens sachent qu'il est plus sûr d'en hériter.

cregox
la source
2
"Problème résolu" - Exactement.
Robert Harvey
@RobertHarvey Ce n'est pas résolu, comme expliqué à droite dans le paragraphe suivant.
cregox
8
Vous êtes juste fou parce que vous ne pouvez pas prolonger le cours. Cela ne signifie pas que ce sealedn'est pas un outil utile pour les concepteurs de framework. Les classes dans un cadre doivent être des boîtes noires; vous ne devriez pas avoir à connaître les internes d'une classe pour pouvoir l'utiliser correctement. Pourtant, c'est exactement ce que demande l'héritage.
Robert Harvey
Je n'ai jamais dit que ce n'était pas utile. Je dis que je ne vois pas son utilisation et je précise pourquoi. Je vous en supplie, donnez-moi une bonne raison de l'utiliser! Même si c'est juste "parce que je veux suivre un modèle de conception fermé", ça va. Je ne vois personne donner explicitement cette raison.
cregox
7
La bonne raison est que vous n'avez pas à prendre en charge l'héritage sur une classe scellée.
Robert Harvey