Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>The simplest way would be to use Java's built-in instanceof operator. For example:</p> <pre><code>public boolean isAAA(Thing myThing) { return myThing instanceof AAA; } </code></pre> <p>Many people, however, would tell you that using instanceof is symptomatic of poor class design, and that the proper way to achieve different behavior with different subclasses is through polymorphism. The problem here is that it it's very easy in Java to get a class to do something different based on what derived type it is, but it's a bit tricky getting some other object to treat a Thing differently depending upon what derived type it has a handle on. This is the <a href="http://en.wikipedia.org/wiki/Double_dispatch" rel="nofollow">Double Dispatch</a> problem.</p> <p>It would be ideal if, when handling your Thing object, you could just dispatch the problem to some other methods that would do different things with the Thing depending on what subclass it is, like so:</p> <pre><code>public void handleThing(Thing myThing) { reactToThing(myThing); } public void reactToThing(AAA myThing) { // Do stuff specific for AAA } public void reactToThing(BBB myThing) { // Do stuff specific for BBB } public void reactToThing(Thing myThing) { // Do stuff for generic Thing } </code></pre> <p>In Java, however, which only supports single dispatch, regardless of the actual type of myThing in handleThing(), reactToThing(Thing) will always get called, and you'll never get your unique behavior.</p> <p>What you need to do to get around this problem is use the <a href="http://en.wikipedia.org/wiki/Visitor_pattern" rel="nofollow">Visitor Pattern</a>. This just involves putting some extra code in your Thing class and all its children to give your reactToThing() methods some extra context. So let's say the above methods are all in a class called Visitor. We can rewrite the above to work by first handing the problem off to the Thing object itself, then polymorphism will give us an appropriate context (Thing, AAA, or BBB) for the object to give back to the Visitor.</p> <p>So, we can rewrite the example above as follows:</p> <pre><code>public class Visitor { // ... public void handleThing(Thing myThing) { myThing.accept(this); } public void reactToThing(AAA myThing) { // Do stuff specific for AAA } public void reactToThing(BBB myThing) { // Do stuff specific for BBB } public void reactToThing(Thing myThing) { // Do stuff for generic Thing } } public class Thing { // ... public void accept(Visitor visitor) { visitor.reactToThing(this); } } public class AAA { // ... public void accept(Visitor visitor) { visitor.reactToThing(this); } } public class BBB { // ... public void accept(Visitor visitor) { visitor.reactToThing(this); } } </code></pre> <p>So why did I need to rewrite the same accept() method in both subclasses? Because otherwise the object would still be in a Thing context when calling the visitor.reactToThing(this) method, and thus we have the same problem as before. By reimplementing it in all three places, the derived class overrides the parent's implementation, and the correct method is called in Visitor.</p> <p>Seems like a lot of work when all you want to know is what derived class you're working with, but the payoff is extensibility and maintenance. Now you don't need to go around adding if (something instanceof somethingElse) all over the place. Specifically, you'll have less duplicate code you need to maintain if you ever decide you need to change something down the road, like extend Visitor, for example.</p> <p>Hope that addresses your question.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload