简体   繁体   中英

How can I perform a generic cast to the correct subclass type?

Currently I have the following code for a method that I have created:

public boolean overlaps(CollisionBody2D collider)
{
    //other method code
    if (collider instanceof ArcBody2D)
        return this.overlaps((ArcBody2D) collider);
    else if (collider instanceof CircleBody2D)
        return this.overlaps((CircleBody2D) collider);
    else if (collider instanceof PointBody2D)
        return this.overlaps((PointBody2D) collider);
    else if (collider instanceof LineBody2D)
        return this.overlaps((LineBody2D) collider);
    else if (collider instanceof BoxBody2D)
        return this.overlaps((BoxBody2D) collider);
    return false;
}

Each of ArcBody2D etc. are subclasses of CollisionBody2D and have defined methods for collisions for each of the other types (ArcBody2D etc.).I want to replace the eyesore if statement (if instanceof)... with a generic cast down to the proper subclass type so that I do not have to continuously grow the if statement as I add more collider types.

Ideally I am trying to achieve something like:

return this.overlaps((collider.subclassType()) collider);

I have tried using generics, but the problem is that it requires you to predefine the class type, which isn't really helpful to me as I need a method which handles collision without needing to predefine the type of CollisionBody2D when called. For example:

BoxBody2D box = new BoxBody2D(parameters);
CollisionBody2D colliders [];
//populate array
for (CollisionBody2D c: colliders)
{
    if (box.overlaps(c))
        //do something
}

I have tried using generics but the problem is they still require you to define the type when the method is called. Is there any other way to achieve this aside from this long if statement?

I believe you can do something along the lines of (exception handling omited)

public boolean overlaps(CollisionBody2D collider)
{
    Class c = collider.getClass();

    return this.overlaps( c.cast( collider) );
}

I think this sounds like a design problem.

Why don't you use an interface instead of a class ?

public boolean overlaps(Collidable collider) {
    return collider.overlaps(this);
}

You would need a new interface that would look something like this:

public interface Collidable {
    boolean overlaps(Collidable collider);
}

You may use a "same class collider" or whatever you need:

public class SameClassCollider implements Collidable {
    @Override
    public boolean overlaps(Collidable collider) {
        return (collider instanceof this.getClass());
    }
}

I mainly suggested to use a Strategy pattern . You may also would like to take a look at the Decorator pattern in case you may want to build more sofisticated collitions.

Here are the steps (mechanism) you have to follow. I have used generic methods to fulfill this. The steps are as following.

  1. Make sure your "overlaps" method is also defined in the super class (CollisionBody2D) and has been overridden accordingly in your subclasses (ArcBody2D etc.) this is if you need to use runtime polymorphism at a later stage
  2. Make "overlaps" method a generic method as following :

    public boolean overlaps(T t){ //your code }

  3. Finally, inside a method you can call this as following :

    new CollisionBody2D.overlaps(new ArcBody2D());

So, you will not need to cast or anything, and it will call the overlaps method in CollisionBody2D class. However, if you need to run the overlaps method of the object you are passing, I recommend you to use runtime polimorphism and go on accordingly, but as for your question above I don't think you have such a requirement than to call the overlaps method of the class which you are referring.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM