views:

218

answers:

3

I'm rather new to Java. After just reading some info on path finding, I read about using an empty class as an "interface", for an unknown object type.

I'm developing a game in Java based on hospital theme. So far, the user can build a reception desk and a GP's office. They are two different types of object, one is a Building and one is a ReceptionDesk. (In my class structure.)

My class structure is this:

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

The problem comes when the usable item can be rotated and the building cannot. The mouse click event is on the grid, so calls the same method. The GP's office is a Building and the reception desk is a ReceptionDesk. Only the ReceptionDesk has the method rotate. When right clicking on the grid, if in building mode, I have to use this "if" statement:

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

I then have to create a new ReceptionDesk, use the rotate method, and the put that reception desk back into the currentBuilding GridObject.

I'm not sure if I'm explaining myself very well with this question. Sorry. I am still quite new to Java. I will try to answer any questions and I can post more code snippits if need be. I didn't know that there might be a way around the issue of not knowing the class of the object, however I may also be going about it the wrong way.

I hadn't planned on looking into this until I saw how fast and helpful the replies on this site were! :)

Thanks in advance.

Rel

+7  A: 

You don't want to check the class of an object before doing something with it in your case. You should be using polymorphism. You want to have the Interface define some methods. Each class implement those methods. Refer to the object by its interface, and have the individual implementations of those objects return their values to the caller.

If you describe a few more of the objects you think you need, people here will have opinions on how you should lay them out. But from what you've provided, you may want a "Building" interface that defines some general methods. You may also want a "UsableItem" interface or something more generic. Hospital could be a class that implements building. ReceptionDesk could implement UsableItem. Building could have a grid of UsableItem inside it.

If rotate() was a common method to all furniture that actually did some work, you may consider making an AbstractUsableItem class that was an abstract class implementing UsableItemand providing the rotate() method. If rotate was different in each implementing class, you would have that method in the interface, but each class, like ReceptionDesk would do its own thing with the rotate() method. Your code would do something like:

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

In your example, if your mouse click on a screen rotated the object under it, and you really did need to check to see if the object could be rotated before doing something like that, you'd do

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

where UsableItem was the interface or abstract class. Some people feel that all design should be done via an interface contract and suggest an interface for every type of class, but I don't know if you have to go that far.

John Ellinwood
Thanks for this useful answer and information. I will have to read over it a bit more before I understand it fully, although from the example you linked me to, this looks like the proper way I should be doing things here.
Relequestual
I have read further into this, read the link you gave and links on that site. good resource. This is defiantly the answer I was after, although it did assume i understand what abstraction and interfaces were, which i didnt, but i guess that was a fair assumption.
Relequestual
+3  A: 

You might consider moving in a totally different direction and having the objects themselves decide what kind of action to take. For example, the GridObject interface might specify function declarations for handleRightClick(), handleLeftClick(), etc. What you'd be saying in that case is "any class who calls themselves a GridObject needs to specify what happens when they are right-clicked".

So, within the Building class, you might implement handleRightClick to do nothing (or to return an error). Within the ReceptionDesk class, you would implement handleRightClick to rotate the desk.

Your code snippet would then become:

currentBuilding.handleRightClick(... any necessary parameters ...);
Elliot Nelson
This looks like the sort of thing i was looking for! brilliant idea! Im sure John's answer is very good, but it may be just a bit over my head.I would have to have the same methods in the GridObject class, and have it empty, while having the methods of the same name in the other classes do things.
Relequestual
+1  A: 

You are correct to be worried. A good rule of thumb for Object-oriented design is that whenever you use a construct like if(x instanceof Y) or if(x.getClass().equals(Y.class)), you should start thinking about moving methods up or down, or extracting new methods.

Elliot and John have both presented good ideas on very different directions you could go, but they're both right in that you should definitely move in some direction. Object oriented design is there to help your code become more legible by making branching for different sorts of behaviors more implicit. Examining what sort of object you're looking at and determining what to do based on that can defeat the purpose of using object-oriented design.

I should also warn you that an interface isn't exactly an empty class. There are some significant differences between empty, abstract classes with abstract methods and interfaces. Instead of thinking of an interface as an empty class, think of an interface as a contract. By implementing an interface, your class promises to provide each of the methods listed in the interface.

CaptainAwesomePants
Thanks. I do indeed intend to create method calls for the inside of the if statements, although im not sure what you mean by "moving methods up or down". could you possibly explain this for me?I cant say i understood all of what they said if im honest. I will have to read up on this area.
Relequestual
I meant moving the methods to either a super class (moving it up) or to a subclass (moving it down). Sorry for the weird jargon. I've been reading too many books on refactoring lately :)
CaptainAwesomePants
I've been thinking about this for quite some time (Eventualy got round to sorting it out). I see what your saying with regards to defeating the point of using object orientated design, but I think I can still justify it, as some methods and variables are still in the superclass's. I'm just about to (not sure if it has a name), change classes from normal classes which are superclass's to abstract classes
Relequestual
If you want to be formal, you're performing a "Push Down Method" refactoring (Fowler, "Refactoring", p. 328). If you're using Eclipse, I believe there's even a Wizard that will do it for you.
CaptainAwesomePants
Fantastic. I feel clever knowing the correct names. I write stuff explaining stuff to people, and it reads like gibberish, but i understand it :). I saw the wizard for refractoring, but I think id rather do it by hand tbh, untill I fully understand the implications of using such powerful wizard tools :)Is there any documentation for them? I ask not because I am lazy, but I want it for the record on here, as its my scrap book of coding genius, and your name is well earnt :p
Relequestual
The Eclipse documentation almost surely has something, though I'd have to check. Also random googling produced this: http://www.scribd.com/doc/18137/Eclipse-tutorial-part-13-Refactoring-in-Eclipse
CaptainAwesomePants