Les classes imbriquées sont-elles sous-évaluées?


9

Je n'essaie pas de dire que je sais quelque chose que tout le monde ne sait pas, mais j'ai résolu de plus en plus de conceptions avec l'utilisation de classes imbriquées, donc je suis curieux de me faire une idée de l'acceptabilité d'utiliser ce qui semble rarement utilisé mécanisme de conception.

Cela m'amène à la question: est-ce que je suis sur un chemin intrinsèquement mauvais pour des raisons que je découvrirai quand ils reviendront me mordre, ou les classes imbriquées sont-elles peut-être quelque chose qui est sous-estimé?

Voici deux exemples pour lesquels je viens de les utiliser: https://gist.github.com/3975581 - le premier m'a aidé à garder ensemble des éléments héréditaires étroitement liés, le second m'a permis de donner accès aux membres protégés aux travailleurs ...


Je veux juste dire merci pour les réponses / idées - je ne sais pas comment choisir une réponse, donc je vais le laisser pendant que je réfléchis aux conseils que j'ai reçus et que je
revois

Réponses:


6

Je n'appellerais pas cela un "mécanisme de conception rarement utilisé" - du moins pas universellement: bien qu'il existe des boutiques où certains contributeurs peuvent désapprouver l'utilisation de classes imbriquées, ce n'est pas du tout une fonctionnalité obscure.

Bien que l'existence de classes avec visibilité d'assemblage et l'introduction de lambdas aient considérablement réduit le besoin de classes imbriquées * , elles restent un choix de conception valide. Bien qu'il existe un certain chevauchement avec les classes internes à l'intérieur d'un espace de noms, la fonctionnalité des classes imbriquées est unique en vous permettant de masquer une classe entièrement à l'intérieur d'une autre classe.


* L'utilisation d'une fonctionnalité similaire en Java est beaucoup plus élevée, car les autres alternatives disponibles en C # ne sont pas là en Java.


Est-il donc bon de cacher une classe entièrement dans une autre classe selon l'essence de la conception OOP?
Maxood

1
@Maxood Il est bon de cacher une classe si vous pouvez la cacher. L'utilisateur de votre API doit en savoir le moins possible sur la façon dont votre API est implémentée.
dasblinkenlight

3

Considérez un instant que vous écrivez une classe dans une autre classe, qui ne sera jamais utilisée ailleurs dans votre programme. Parce que si vous l'utilisiez ailleurs, vous en feriez un cours public ordinaire, comme tous les autres.

Donc, la chose qui est censée rendre la POO excellente (réutilisabilité) est absente ici. En outre, que pourriez-vous réaliser avec une classe imbriquée que vous ne pourriez pas réaliser avec des méthodes ordinaires et des membres privés au sein de la classe parente?

Pour un modèle logiciel utile utilisant des classes imbriquées, regardez ici .


10
Je n'ai jamais acheté la chose réutilisable, du moins pas la façon dont elle est habituellement présentée. (1) L'appel à du code / des classes existantes (dont vous semblez parler et que je considère généralement comme une définition de la réutilisation) n'a absolument rien à voir avec la POO, c'est juste une modularité de base. (2) Le polymorphisme de sous-type, qui est une caractéristique déterminante de la POO, permet la réutilisation du code client en rendant l'implémentation spécifique non pertinente , c'est-à-dire qu'il fonctionne exactement de la même manière, que la classe concrète soit accessible ou non. IOW c'est la réutilisation que j'achète, mais cela fonctionne aussi bien avec les classes imbriquées.

1
Je dirais qu'il y a aussi l'isolation de l'espace de noms donnée par la classe parent - donc si vous le vouliez, les classes A et B pourraient avoir imbriquées la classe "Params", et l'accès aux membres non publics de la classe contenante. Ne sont-ils pas les deux raisons d'avoir des classes internes utilisées en dehors de la classe?
Aaron Anodide

@AaronAnodide Cela devrait être une réponse sur un bon moyen d'utiliser des classes imbriquées. C'est exactement comment / pourquoi je les utilise, cela aide à organiser le code.
Izkata

2

am I going down an inherintly bad path

Je pense que dans votre deuxième exemple (les sous-classes de travailleurs), vous l'êtes certainement. Vous avez mappé chaque sous-classe à un état spécifique dans la super classe. Alors maintenant, chaque fois que vous souhaitez ajouter un état à la super classe, vous devrez modifier trois emplacements (ajouter un état à la super classe, ajouter une nouvelle sous-classe et changer le constructeur de la classe dérivée pour ajouter la sous-classe à la liste ).

L'utilisation de classes imbriquées pour accéder aux membres privés semble être une utilisation valide (je ne l'ai jamais fait personnellement) mais votre cas spécifique ne fonctionne pas ici.

Comme pour l'exemple de la partie du corps. Étant donné que toutes les classes imbriquées sont publiques, vous ne faites pas grand-chose sauf l'espace de noms. Si ces classes se développent pour inclure plus de fonctionnalités, vous constaterez peut-être que les classes imbriquées encombrent simplement les interfaces et vous parcourez le code pour trouver quelque chose de spécifique. Je remarque également que parce que vous avez des classes imbriquées, vous êtes obligé de rompre les conventions de dénomination et de nommer vos classes en minuscules (c'était peut-être un choix). Mais ces arguments sont plus superficiels que tout ce qui est réellement faux.

À moins, bien sûr, que vous ayez besoin de mettre en œuvre un bras désincarné. Ensuite, créer un bras en procédant comme suit est déroutant car il n'y a pas de corps / torse / côté. (Notez également le boîtier déroutant).

arm newArm = new Body.torso.side.arm("");

1

Le seul avantage que je puisse penser des classes imbriquées est qu'elles peuvent être rendues privées (ou protégées). Je dirais que dans ce cas, les classes imbriquées peuvent vous aider à encapsuler des fonctionnalités si une classe est destinée à être utilisée par la classe externe et cette classe seule.


1

D'après mon expérience, les classes imbriquées

  • Je suis revenu me hanter
  • Ont été utilisés quand je voulais couper les coins ronds
  • Faire des tests un cauchemar
  • A eu un impact négatif sur la séparation des préoccupations et la conception globale

J'ai jeté un coup d'œil à votre classe, et tout de suite je pense que:

  • C'est pénible à regarder car la classe est énorme
  • Je ne peux pas tester les "doigts" sans créer à peu près tout le corps
  • Je ne peux pas avoir plusieurs implémentations de torse. Cela ne semble pas évident dans un contexte de "corps humain", mais dans un scénario différent, cela deviendrait évident.

Pourquoi ne pas séparer votre classe en plusieurs classes et leur donner des espaces de noms séparés. Par exemple

WindowsGame1.PhysicalModel.UpperBody
WindowsGame1.PhysicalModel.LowerBody
WindowsGame1.PhysicalModel.UpperBody.Arms
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.