2009-04-09 9 views
3

Je suis plutôt nouveau à Java. Après avoir lu quelques informations sur la recherche de chemin, j'ai lu à propos de l'utilisation d'une classe vide comme "interface", pour un type d'objet inconnu.Serait-ce le bon endroit pour utiliser le mot-clé java "interface"?

Je développe un jeu en Java basé sur le thème de l'hôpital. Jusqu'à présent, l'utilisateur peut construire une réception et un bureau de médecin généraliste. Ils sont deux types d'objets différents, l'un est un Building et l'autre est un ReceptionDesk. (. Dans ma structure de classe)

Ma structure de classe est la suivante:

GridObject-->Building 
GridObject-->Item-->usableItem-->ReceptionDesk. 

Le problème vient quand on peut faire tourner l'élément utilisable et le bâtiment ne peut pas. L'événement de clic de souris est sur la grille, appelle donc la même méthode. Le bureau du médecin généraliste est un Building et le bureau de réception est un ReceptionDesk. Seul le ReceptionDesk a la méthode rotate. Lorsque un clic droit sur la grille, si en mode de construction, je dois utiliser cette « if »:

if (currentBuilding.getClass.equals(ReceptionDesk.getClass) 

J'ai alors de créer une nouvelle ReceptionDesk, utilisez la méthode rotate et la vente qui réception retour dans le currentBuilding GridObject.

Je ne suis pas sûr si je m'explique très bien avec cette question. Pardon. Je suis encore assez nouveau à Java. Je vais essayer de répondre à toutes les questions et je peux poster plus de coupons de code si besoin est. Je ne savais pas qu'il pourrait y avoir un moyen de contourner le problème de ne pas connaître la classe de l'objet, mais je peux aussi m'y prendre à tort.

Je n'avais pas prévu d'étudier cela avant d'avoir vu la rapidité et l'utilité des réponses sur ce site! :)

Merci d'avance.

Rel

Répondre

7

Vous ne voulez pas vérifier la classe d'un objet avant de faire quelque chose avec elle dans votre cas. Vous devriez utiliser polymorphism. Vous voulez que l'interface définisse certaines méthodes. Chaque classe implémente ces méthodes. Reportez-vous à l'objet par son interface et demandez aux implémentations individuelles de ces objets de renvoyer leurs valeurs à l'appelant.

Si vous décrivez un peu plus d'objets dont vous pensez avoir besoin, les gens ici auront des opinions sur la façon dont vous devriez les exposer. Mais à partir de ce que vous avez fourni, vous voudrez peut-être une interface «Bâtiment» qui définit certaines méthodes générales. Vous pouvez également vouloir une interface "UsableItem" ou quelque chose de plus générique. L'hôpital pourrait être une classe qui implémente le bâtiment. ReceptionDesk pourrait implémenter UsableItem. Le bâtiment pourrait avoir une grille de UsableItem à l'intérieur. Si rotate() était une méthode courante pour tous les meubles qui ont effectivement travaillé, vous pouvez envisager de créer une classe AbstractUsableItem qui était une classe abstraite implémentant UsableItem et fournissant la méthode rotate(). Si la rotation était différente dans chaque classe d'implémentation, vous auriez cette méthode dans l'interface, mais chaque classe, comme ReceptionDesk ferait sa propre chose avec la méthode rotate().Votre code ferait quelque chose comme:

UsableItem desk = new ReceptionDesk(); 
desk.rotate() 

Dans votre exemple, si votre clic de souris sur un écran tourné l'objet au-dessous, et vous aviez vraiment besoin de vérifier pour voir si l'objet peut être tourné avant de faire quelque chose comme cela, vous le feriez

if (clickedObject instanceOf UsableItem) { 
    ((UsableItem) clickedObject).rotate(); 
} 

où UsableItem était l'interface ou la classe abstraite. Certaines personnes pensent que tout le design devrait être fait via un contrat d'interface et suggérer une interface pour chaque type de cours, mais je ne sais pas si vous devez aller aussi loin.

+0

Merci pour cette réponse et cette information utiles. Je vais devoir relire un peu plus avant de le comprendre pleinement, bien que, d'après l'exemple auquel vous m'avez lié, cela ressemble à la façon dont je devrais faire les choses ici. – Relequestual

+0

J'ai lu plus loin dans ceci, lisez le lien que vous avez donné et les liens sur ce site. bonne ressource. C'est la réponse que j'ai trouvée après, bien que je suppose que je comprends ce que l'abstraction et les interfaces étaient, ce que je n'ai pas, mais je suppose que c'était une supposition juste. – Relequestual

3

Vous pourriez envisager de vous déplacer dans une direction totalement différente et de laisser les objets eux-mêmes décider du type d'action à entreprendre. Par exemple, l'interface GridObject peut spécifier des déclarations de fonctions pour handleRightClick(), handleLeftClick(), etc. Ce que vous diriez dans ce cas est "toute classe qui s'appelle GridObject doit spécifier ce qui se passe quand on clique avec le bouton droit de la souris. ". Ainsi, dans la classe Building, vous pouvez implémenter handleRightClick pour ne rien faire (ou retourner une erreur). Dans la classe ReceptionDesk, vous devez implémenter handleRightClick pour faire pivoter le bureau.

Votre extrait de code deviendrait alors:

currentBuilding.handleRightClick(... any necessary parameters ...); 
+0

Cela ressemble au genre de chose que je cherchais! idée brillante! Je suis sûr que la réponse de John est très bonne, mais c'est peut-être juste un peu dépassé. Je devrais avoir les mêmes méthodes dans la classe GridObject, et l'ai vide, alors que les méthodes du même nom dans les autres classes font des choses. – Relequestual

1

Vous avez raison d'être inquiet. Une bonne règle de base pour la conception orientée objet est que chaque fois que vous utilisez une construction comme if(x instanceof Y) ou if(x.getClass().equals(Y.class)), vous devriez commencer à penser à déplacer les méthodes vers le haut ou vers le bas, ou à extraire de nouvelles méthodes. Elliot et John ont tous deux présenté de bonnes idées sur des directions très différentes, mais ils sont tous les deux justes en ce sens que vous devez absolument vous déplacer dans une certaine direction. La conception orientée objet est là pour aider votre code à devenir plus lisible en rendant plus implicite la dérivation pour différents types de comportements. Examiner quel type d'objet vous regardez et déterminer ce qu'il faut faire en fonction de cela peut aller à l'encontre du but de l'utilisation de la conception orientée objet.

Je devrais également vous avertir qu'une interface n'est pas exactement une classe vide. Il existe des différences significatives entre les classes abstraites vides et les méthodes et interfaces abstraites. Au lieu de considérer une interface comme une classe vide, pensez à une interface en tant que contrat. En implémentant une interface, votre classe promet de fournir chacune des méthodes listées dans l'interface.

+0

Merci. J'ai en effet l'intention de créer des appels de méthode pour l'intérieur des instructions if, même si je ne suis pas sûr de ce que vous entendez par "déplacer les méthodes vers le haut ou vers le bas". pourriez-vous expliquer cela pour moi? Je ne peux pas dire que j'ai compris tout ce qu'ils ont dit si je suis honnête. Je vais devoir lire sur cette zone. – Relequestual

+0

Je voulais dire déplacer les méthodes vers une super classe (en le déplaçant vers le haut) ou vers une sous-classe (en la déplaçant vers le bas). Désolé pour le jargon bizarre.J'ai lu trop de livres sur le refactoring ces derniers temps :) –

+0

J'ai réfléchi à cela depuis un certain temps (Eventuellement, j'ai essayé de le résoudre). Je vois ce que vous dites en ce qui concerne l'utilisation de la conception orientée objet, mais je pense que je peux toujours le justifier, car certaines méthodes et variables sont encore dans la superclasse. Je suis sur le point de (je ne sais pas s'il a un nom), changer les classes des classes normales qui sont des classes abstraites – Relequestual