Je me débats avec comment je pourrais éviter d'utiliser une instanceof () dans certains de mes codes. Cet exemple de réveillé quelque peu capture le problème.
Class Meat extends Food; Class Plant extends Food; Class Animal; Class Herbivore extends Animal { void eat( Plant food); } Class Carnivore extends Animal { void eat( Meat food); } Class Omnivore extends Animal { void eat(Food food); } Class Zoo { List<Animals> animals; void receiveFood( Food food) { // only feed Plants to Herbivores and Meat to Carnivores // feed either to Omnivores } }
5 Réponses :
Dans votre cas, si le consommateur de l'objet doit connaître certaines choses à propos de cet objet (par exemple, c'est de la viande de viande), incluez une propriété dans votre classe de base Laisser cette connaissance dans la classe elle-même, plutôt que dans les consommateurs de la classe. P> ISMeat () code> et avoir des sous-classes concrètes remplacent le Mise en œuvre de la méthode de la classe de base pour renvoyer une valeur appropriée. P>
Donc, le cas de mise en place d'une méthode ISMeat () dans la classe de base étant meilleur que d'utiliser l'instance code> est que dans le cas de cette dernière connaissance de la mise en œuvre (possible) est en cours de transfert à la classe client? Je suppose que cela viendrait ensuite à peser ce transfert de connaissances au client avec encombrement de l'objet de base avec iSxxx code> méthodes. Je peux voir que différents cas peuvent peut-être basculer la balance dans les deux sens.
Une solution simple est lorsque vous utilisez plusieurs classes personnalisées interagissant les unes avec les autres, crée simplement ISNOOD (), Isanimal (), Iscarnivore (), etc. Méthodes qui renvoient un booléen en fonction de la classe. Ce n'est pas le Plus jolie mais le travail fait 100% du temps. P>
Voir le commentaire ci-dessus. Vous avez donné fondamentalement la même réponse en même temps!
Élargir sur mon commentaire, je tenterais d'utiliser des génériques pour m'aider ici ici: Notez que cela ne résout pas le problème d'itération via une liste de code> et
animal code> et n'envoie que des aliments appropriés à chaque animal - je ne vois pas un moyen de le faire sans exemple explicite
de chèques de style. Mais cela vous permet d'être plus précis avec ce que vos sous-classes acceptent. P> p>
Voir Stackoverflow.com/questions/9806785/... Cette question a été mentionnée ci-dessus, mais il discute de certains des pièges potentiels d'une telle utilisation des génériques. Pour l'enregistrement, cependant, j'avais déjà envisagé d'une telle solution.
Une autre solution consiste à maintenir 2 listes: une pour herbivores et une pour les carnivores. P>
C'est une chose que j'ai pensée, mais il semble que j'avais encore besoin d'utiliser l'instanceOf () pour tester le type de nourriture pour décider de la liste des aliments.
Eh bien, vous auriez également besoin de canaliser des canaux pour obtenir de la nourriture: on ne fournit que des plantes que l'autre fournissant de la viande.
Le motif de visiteur résout votre problème. Voici le code: exécutant le zoo code> impressions de démonstration p>
Code refactored en extrayant l'interface animalvistor de la nourriture de classe
Bien que le Nerd en moi aime voir le code pour le modèle de visiteur en action (Bravo!), Il a été conçu pour ajouter de nouveaux visiteurs sans casser les classes visitées, et non pour éviter l'instanceOf (qui est la question de la question). Les solutions de propriété (ISMeat () etc.) sont moins complexes et Humbler < / a>.
Peut-être devriez-vous examiner des méthodes génériques? De cette façon, vous pouvez spécifier qu'un animal a une méthode mangée (T étendre la nourriture) et l'herbivore serait dactylographié comme une plante? Quelque chose le long de ces lignes.
duplicailler possible de est cette utilisation de l'opérateur "Instanceof" Considéré comme mauvais design?
Candidat parfait pour le modèle de visiteur
Hmmm ... une solution de modèle de visiteur n'a-t-elle pas un problème similaire (1) ci-dessus? Lorsque la nourriture est reçue, un animal devrait être visité même s'il n'a pas mangé le type de nourriture? Un exemple de visiteur serait génial-- Je ne suis jamais sûr si je reçois complètement ce modèle dans certains contextes ...
Votre préoccupation concernant l'inefficacité n'est probablement pas très bien fondée. Chaque animal doit être nourri, le coût d'itération va donc être linéaire. Dans le pire des cas (où chaque animal est un herbavore), vous allez nourrir
N code> mais demandant la permission
2 * n code> fois. Ceci est très probablement une inefficacité raisonnable. Si vous vous nourrissez très souvent et que les configurations d'animaux changent rarement, cela peut valoir la pré-traiter dans des listes d'herbavores, d'omnivores et de carnivores.
Quelle est l'interface de l'animal super type? Est-ce que cela traite avec? Si tel est le cas, toute l'abstraction des animaux et de la nourriture ne serait-elle pas une violation du principe de substitution de Liskov? Peut-être que OOP n'est pas toujours la meilleure abstraction des taxonomies de la nature ...
Je dirais probablement que c'est un abus d'héritage. @nansen a raison, cela viole l'un des principes solides. La violation du LSP ne vous fera aucune fin du chagrin, malheureusement, vous ne vous en ressent souvent pas la majeure jusqu'à ce que vous soyez bien dans votre implémentation.
Cela semble très similaire à celui-ci Stackoverflow.com/Questtions/9806785/...