1

I am creating some sort of Achievement system and I have a class KillXEnemies and then I inherit from it with classes like KillXEnemiesWeapon (enemies killed with an certain weapon). And when you kill an enemy I loop trough the achievement objects and add that an enemy has been killed with:

if(object instanceof KillXEnemies)
    ((KillXEnemies)object).addEnemyKilled();

But then the KillXEnemiesWeapon gets tracked as well because it inherits from KillXEnemies. I know one solution is:

if(object instanceof KillXEnemies && !(object instanceof KillXEnemiesWeapon))
    ((KillXEnemies)object).addEnemyKilled();

But I am about to get quite many classes that inherits from KillXEnemies and it seems to be a bad solution to have like 20 !(object instanceof (---))

So I am wondering if there is an easier way to check if the object only is KillXEnemies and not KillXEnemiesWeapon

4

5 回答 5

5

You can use Object#getClass to get the object's actual class, then compare that to KillXEnemies.class.

if (object.getClass().equals(KillXEnemies.class))

That will be true of object is a KillXEnemies but not if object is an instance of a subclass of it.

But I wonder (and recognizing that you have a lot more information to work with than I do, so I could easily be wrong) if classes and subclasses are the best way to model this information...

于 2013-03-15T08:53:55.307 回答
1

Maybe consider adding arguments to your addEnemyKilled() method to include some metadata, such as the Enemy that was killed or the Weapon that was used, etc.

That way, the classes themselves can overload the method and will have the relevant information needed to act accordingly.

(Just one idea on how you could get the logic into the classes themselves and out of crazy instanceof or class checking.)

于 2013-03-15T09:13:54.370 回答
0

Use poor man RTTI. Make each of your concrete class implement a base getObjType() method. It may end up cleaner and faster than a forest of instanceof.

switch(obj.getObjType()){
   case KillXEnemies.TYPE_ID:
       doSomething((KillXEnemies)obj);
   break; 
  case KillXEnemiesWeapon.TYPE_ID:
       doSomething((KillXEnemiesWeapon)obj);
   break;
   //and so on ...
}
于 2013-03-15T08:53:58.113 回答
0

How about adding a flag, something like parentClass, which is true for parent class and false for all subclasses? So your condition would be if(object instanceof KillXEnemies && ((KillXEnemies)object).isParentClass()) {

于 2013-03-15T08:54:43.597 回答
0

I would do this with overridden methods. Have a method public boolean doesKillEnemies() in KillXEnemies. Provide a default implementation and wverride as appropriate to make it return true in those classes whose objects do kill enemies, and false in all other subclasses.

The test then becomes:

if(object instanceof KillXEnemies && ((KillXEnemies)object).doesKillEnemies())
    ((KillXEnemies)object).addEnemyKilled();
于 2013-03-15T09:01:16.727 回答