Okay, suppose I have a class A and subclasses B, C, D, E, F, G. I have a function:

public void foo (A object)

I have the default function handler which handles A objects which aren't subclassed, and the B, C, and D subclasses. Subclasses of type E, F, G have special needs, so there are functions for them, so four functions altogether:

public void foo (A object)
{
     // handle when object is not of type E, F, G
}

public void foo (E object)
{
     // handle when object isof type E
}

public void foo (F object)
{
     // handle when object is of type F
}

public void foo (G object)
{
     // handle when object is of type G
}

These functions are all in the A class. Function call is this:

A a = new A ();
A e = new E ();
a.foo (e);

The function that needs to get implemented is the function foo that takes a parameter of type E. The above function call goes to the function that takes a parameter of type A. In the function that takes a parameter of type A, I can do this to redirect it:

public void foo (A object)
{
     if (object instanceof E)
          foo ((E) object); // typecast to type E
     else if (object instanceof F)
          foo ((F) object); // typecast to type F
     else if (object instanceof G)
          foo ((G) object); // typecast to type G
     else
     {
         // code to handle the other cases
     }
}

Is there a better way? There are actually many more than three subclasses that need the special handling, so that's a long if-else if-else statement.

Recommended Answers

All 11 Replies

>Is there a better way?
Yes, design the class hierarchy such that you don't need to know the dynamic type of the object. Perhaps some form of strategy pattern would clean up that selection code.

commented: Definitely the easiest way to fix the problem! =) +4

Bah, disregard this post >_<

public <T extends A> void doSomething(T type){

      if(type instanceof [SpecialNeedClass]){
              // typecast only for this type
      }
      // else if(...) // other specialized types
      else{ // if no other specialized type, perform basic A operations
        
      }

}

It would've been a good idea if Incomplete types were allowable in Java, but unfortunately Java isn't the same as C++ @_@

>Is there a better way?
Yes, design the class hierarchy such that you don't need to know the dynamic type of the object. Perhaps some form of strategy pattern would clean up that selection code.

Would an Adapter be overkill?

I.E.

public class AdaptedA<T extends A> extends A{

      private T myType = null;
      public AdaptedA(T type){
             myType = type;
      }

      T getType(){ return type; }

      void performSpecializedOperation(Object parameters...){
                // your if statements here...
      }
}
public void foo(A object, Object parameters...){

      if(object instanceof AdaptedA){
            ((AdaptedA)object).performSpecializedOperation(parameters);
      }else{
          // basic commands for A objects
      }

}

The only advantage to this is centralizing the code in the Adapter class and not the method that handles A-types.

Hopefully this is reasonable @_@

That still involves runtime instanceof checks. I would agree with Narue's suggestion.

commented: Yeah, I do to! I was hoping my suggestion would be reasonable, though you make a good point. +4

>Is there a better way?
Yes, design the class hierarchy such that you don't need to know the dynamic type of the object. Perhaps some form of strategy pattern would clean up that selection code.

Basically it's a game application where a whole bunch of objects float around. If two objects collide with each other, the default behavior is they both blow up, but not always (hence the subclasses that have different implementations), and some things blow up when they hit some types of objects, but not others. So you really need to know the type of each object. There's no way to know ahead of time how many of what object there is going to be, nor can you know what will hit what, since it's all done randomly and based on user input. Basically there is a Collection of type A which contains all of the objects floating around.

So I'm getting from these posts (and Alex, I looked at the Rep comments you gave and it sounds like you no longer like your proposed solution) that there is no easy way to typecast in the situation I listed and if you don't want all of those "else if" statements (which I imagine defeats the whole Object Oriented idea?) then you really need to go back to the drawing board on the underlying design. No quick fix for the function the way it is? Is there no way to typecast in Java without hardcoding what you are type-casting to? Thanks for the replies.

You could use a State Machine, or State Pattern based on how many times an object has been encountered, or the State of an object can depend on the type of object it encounters...

It may simplify things, but only if you can work out the different possible states of objects.

I think this is the closest thing to a solution to your problem, though considering I know what you're trying to do, and State patterns can be bulky... it can be somewhat complicated @_@

I still struggle making State Patterns, unless I study the behavior between objects thoroughly. Below is just a sample program. a collides into b multiple times, and the behavior is different each time.

Of course this is just a test program, but the concept may be powerful enough to provide a solution to the problem O_O

/**
 * Just testing the State Pattern =)
 */
public class TestingGrounds{

	/**
	 * Interface for all Collidable objects
	 */
	interface Collidable{

		public void collideInto(Collidable other); // collide into the object

		public void react(Collidable theCollider); // triggered from another object

		public void setState(SomeObjectState behavior); // set the behavior of the object
	}

	/**
	 * The State of SomeObject has the same exact interface as the Object itself
	 */
	abstract class SomeObjectState implements Collidable{

		protected Collidable ref = null;

		public SomeObjectState(Collidable ref){
			this.ref = ref;
		}

		public void setState(SomeObjectState behavior){} // hook, States aren't meant to be composite @_@
	}

	/**
	 * The Normal State of an object.
	 *
	 * Nothing out of the ordinary happens in this state, but it's such a boring state... it doesn't want
	 * to belong to any object for long! After it is ready to do a transition it will transfer the
	 * state of the object reference to a Bouncing State.
	 */
	class NormalState extends SomeObjectState{

		private boolean ready = true;

		public NormalState(Collidable ref){
			super(ref);
		}

		public void collideInto(Collidable other){
			ready = (ready) ? false : true;

			if(ready){
				System.out.println(ref+ " -> collideInto -> " + other);
				System.out.println(ref + " is Ready to make a transition! O_O");
				ref.setState(new BouncingState(ref));
				other.react(this);
			}else{
				System.out.println("Not quite ready yet...");
			}
		}

		public void react(Collidable theCollider){

			if(!ready){
				System.out.println("Hey, don't bug me X_X");
			}else{
				System.out.println("Whoo! O_O");
			}
		}
	}

	/**
	 * The Bouncing State
	 *
	 * This State means business! After colliding into objects a few times it will
	 * transfer its momentum into another object (hence the other object will become bouncy, and the original
	 * object that encapsulated this behavior will become "Normalized" X_X )
	 */
	class BouncingState extends SomeObjectState{

		private int bounceCount = 0;

		public BouncingState(Collidable ref){
			super(ref);
		}

		public void collideInto(Collidable other){
			bounceCount = (++bounceCount)%3;
			System.out.print(ref + " -> collideInto -> " + other);
			if(bounceCount == 0){
				System.out.println("Momentum Transfer!");
				other.setState(new BouncingState(other));
				ref.setState(new NormalState(ref));
			}else{
				System.out.println("Bloop...");
			}
		}

		public void react(Collidable theCollider){
			System.out.println("Reaction! O_O");
		}

	}

	/**
	 * Typical class for SomeObjects (whatever that type may be O_O )
	 */
	abstract class SomeObject implements Collidable{

		protected SomeObjectState currentState = null;

		public void collideInto(Collidable other){
			currentState.collideInto(other);
		}

		public void react(Collidable theCollider){
			currentState.react(theCollider);
		}

		public void setState(SomeObjectState behavior){
			this.currentState = behavior;
		}
	}

	/**
	 * Typical 'foo; class, named A
	 */
	class A extends SomeObject{

		public A(){
			currentState = new NormalState(this);
		}

		@Override public String toString(){
			return "[A]";
		}
	}

	/**
	 * Another test class, named B for simplicity @_@
	 */
	class B extends SomeObject{
		public B(){
			currentState = new BouncingState(this);
		}

		@Override public String toString(){
			return "[B]";
		}
	}

	/**
	 * Entry point of the TestingGrounds
	 */
	public static void main(String... args){
		TestingGrounds tg = new TestingGrounds();

		TestingGrounds.A a = tg.new A();
		TestingGrounds.B b = tg.new B();

		a.collideInto(b);
		a.collideInto(b);
		a.collideInto(b);
		a.collideInto(b);
		a.collideInto(b);
		a.collideInto(b);
		//b.collideInto(a);
		//b.collideInto(a);
		//b.collideInto(a);
		//b.react(a);
		//a.react(b);
	}
}

Edit: you can implement a completely different set of States for each object, but the interface will remain nearly the same.

Again, only consider this if it's the only option. By initializing a particular State for an object and having it transition based on conditions, you can have Objects of the same base type interact the same way and leave the "behavior changing" to the encapsulated state.

Vernon, can you post a simple example or two of what determines whether or not the objects blow up? You mentioned that it's not only a matter of the types themselves that determine the result, as in A + B always explodes while A + C never does.

If you can describe the determination of the result a bit more it would help.

Vernon, can you post a simple example or two of what determines whether or not the objects blow up? You mentioned that it's not only a matter of the types themselves that determine the result, as in A + B always explodes while A + C never does.

If you can describe the determination of the result a bit more it would help.

I actually don't know the exact criteria and what happens under all the circumstances. It's not actually my project, but the project of a friend who's taking a first semester Java course. They've been exposed to arrays and Vectors and ArrayLists and the underlying concepts of Object Oriented programming and the assignment is to demonstrate some knowledge of Collections and subclassing. So this person decided to create a bunch of objects (asteroids, spaceships, people, cars, aliens, etc.) that float around and exhibit different behavior when they collide. No floating occurs as it's presently a console application. I'm not entirely sure he's decided exactly what will happen himself yet, but for now it's probably something basic. A console message displays something like "A car and a spaceship collided and blew up." or a "A man and an alien collided. You get a thousand dollars." He definitely wants to display the two object types, which he's doing with getClass ().getName () .

But for the sake of a hypothetical, let's say that you have superclass A. Subclasses B, C, D always explode when they hit anything. Subclass E explodes with 25% probability, subclass F explodes with 50% probability, subclass G with 75% probability. If it doesn't explode, you get money. So you're looking at something like this:

public void collide (A object)
{
     String type1 = this.getClass ().getName();
     String type2 = object.getClass ().getName();
     System.out.println ("There was a collision between "
           + type1 + " and " + type2 + ".  Kaboom!";
}

public void collide (E object)
{
     Random random = new Random ();
     if (random.nextDouble () < 0.25)
          System.out.println ("Kaboom!");
     else
          System.out.println ("You win a thousand dollars.");
}

public void collide (F object)
{
     Random random = new Random ();
     if (random.nextDouble () < 0.50)
          System.out.println ("Kaboom!");
     else
          System.out.println ("You win a thousand dollars.");
}

public void collide (G object)
{
     Random random = new Random ();
     if (random.nextDouble () < 0.75)
          System.out.println ("Kaboom!");
     else
          System.out.println ("You win a thousand dollars.");
}

Anyway, my friend was hoping that, if object was of type G, Java would look for a function that takes a G parameter and if it found one, execute it. If not, it would look for a function that takes its superclass (A) as a parameter and execute that one, but that is not what is happening. All the calls are going to the function that takes an A parameter. There is a Collection of type A and two objects are picked from it to collide, and then the collide function is called and the result is based on the type of that second collision object.

If he can't have it do what he wants in that respect, second best to his way of thinking is to get it to go the function that takes the superclass parameter and divert it from there to the right function, but without the if statements. Is such a thing possible or do you have to do a redesign of the class hierarchy as Narue suggested? By the way, an if statement or two is OK with him, just not requiring an if statement for every subclass that needs special implementation.

You could use a State Machine, or State Pattern based on how many times an object has been encountered, or the State of an object can depend on the type of object it encounters...

Interesting idea. I think designing a state machine to get around the problem of calling the correct function might be a little overkill in this particular case. I'm wondering if there is something more elementary. Thank you!

> Is there a better way? There are actually many more than three subclasses that need the
> special handling, so that's a long if-else if-else statement.

Just create an interface Collidable which exposes a contract of the form Outcome collide(Collidable c) . Make classes implement this interface and implement the logic accordingly, which, based on the source and target colliding objects would determine the outcome of the collision. No need for any run-time type checks, the run-time method invocation based on the actual object in consideration will be automatically taken care of.

> You could use a State Machine, or State Pattern based on how many times an object has been
> encountered, or the State of an object can depend on the type of object it encounters...

KISS ;-)

Thanks for everyone's input! I'll give this a whirl.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.