Thursday, March 20, 2014

Java InstanceOf Alternative with Enum

Hello,

Everyone deals with the instanceof problem in their Java (or is in C#) career. Instanceof isn't just considered wrong by most authors and programmers, but is aesthetically unpleasant.

So many programmers move to design patterns and the Visitor or Composite pattern. While perfectly valid solutions, there is another obvious solution not to be overlooked, particularly when polymorphism fails.

For the Libgdx game framework, I wanted to create a traditional observer - observable class hierarchy independent of the Libgdx framework. For example, for each type of event (a key pressed, the screen touched) I wanted a workflow to create that event, assign observers to it and be done with it.




These events descend from an AbstractEvent object which itself is a subclass of observable. They will be populated by an InputProcessor and GestureListener with the appropriate properties (if you haven't used Libgdx and want to make cross platform Java games I definitely recommend it).

When the Libgdx framework detects an event, it calls an object with the InputProcessor or GestureListener interface to handle the events. However, since I'm creating a class hierarchy outside Libgdx, I needed a way to populate these InputXXXX and GestureXXXX objects dynamically at runtime. For example, if the user pressed the screen, I wanted an object of InputTouchDown populated by Libgdx.

This InputTouchDown will already have been created and have its observers assigned. The issue however is I don't add InputTouchDown instances to the queue. I add AbstractEvent objects to the queue with a method signature like this :

public InputProcessor add(AbstractInput input) {  

So, how exactly does the add method know what is being added? The add method needs to know what is being added because each input event has different properties. For example, some events have x and y coordinates, some have counts, some have buttons. The add method then adds the AbstractInput to the appropriate instance variable (for example, an InputKeyUp instance) so that when an event happens the correct methods are called at runtime by Libgdx to populate it.



As you can see the problem is how to set the inputTouchDown when an AbstractInput is passed to the add method without resorting to instanceof? And even worse (though I don't have to deal with it in the Libgdx framework) how would I know when to call touchDown?

I could either push all the properties of the children into the parent (and pollute the class hierarchy) or find a way to deal with it.  The obvious solution was Visitor or Composite pattern. However, Visitor pattern seemed inadequate. Not only was it a limited number of visits (once every user initiated action) but it is a large number of events. The composite pattern made even less sense, because events are not "composed" of other events.

 


The answer was an enum. Here is the process.

1. Create a final variable in the superclass of the enum's type

2. Create a constructor in the superclass which requires the enum type as a parameter.



Now in the inherited classes, you do not need to put the enum in your constructors. Simply call super with the appropriate enum type within the constructor (do not expose this implementation).



Now a concrete instance variable assigned to an AbstractXXXX instance variable can always determine its correct type without instanceof, perhaps for casting or other runtime operations.

If you find that there are a limited number of subclasses possible for your class hierarchy (usually because you do not control the class hierarchy such as when building adapters for a third party framework), and you dislike the bloat of Visitor or the Composite pattern doesn't make sense, consider using this enum method. It probably violates every principle of object oriented design, but it keeps the codebase simple to debug and intuitive. You will still have the switch statement using getInputType but with aesthetically pleasing enums instead of instanceof calls.

Comments welcome below.

5 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. the sympathetic nervous system of the person are being highlighted whenever there are provocative questions.
    http://www.liedetector.uk

    ReplyDelete
  3. This really answered my problem, thank you!
    Visit Site: https://houseoffuncoins.com/

    ReplyDelete
  4. Assignment Help preparation and submitting assignments and essays before the deadline is a tough nut to crack. It takes extreme dedication. What if, you do not have this much availability? What if, you have planned things that are clashing with your courses? What if, you are regularly getting less grades your courses? If this sounds you fit, then you should probably take Cheap Essay Writing Service Online from GOTOASSIGNMENTHELP service provider. It can take away all the pain you are in. You can get plagiarism free assignment and My Assignment Help and that too with high quality. This can probably bring A+ grade and you can roam proudly with best grades under your arm.

    ReplyDelete
  5. thanks for this amazing post keep posting fullstack java course in pune

    ReplyDelete