I have a tree of projectile classes I am trying to use some reflection to not implement every combination possible by hand when most of it would be copy paste or at best a lot of one liner virtual methods to override attributes.
Basically I have different weapon types that shoot in different patterns such as twin linked, alternating or just a single weapon, and a number of different projectiles such as missiles, bullets, sniper bullets.
The syntax is currently the flavor of:
public Bomber() {
weapons.add(new TwinLinkedWeapon<Missile>(Missile.class));
weapons.add(new Weapon<Bullet>(Bullet.class));
}
and Weapon looks like:
public class Weapon<T extends Projectile> {
long lastShot;
protected Constructor<? extends T> ctor;
public Weapon(Class<? extends T> projectileType) {
try {
ctor = projectileType.getDeclaredConstructor(actor.Actor.class);
} catch (SecurityException e) {
e.printStackTrace();
return;
} catch (NoSuchMethodException e) {
e.printStackTrace();
return;
}
lastShot = 0;
}
protected long getLastShotTime() {
return lastShot;
}
protected T newProjectile(actor.Actor ship){
T projectile = null;
try {
projectile = ctor.newInstance(ship);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return projectile;
}
protected void setLastShotTime(long time) {
lastShot = time;
}
public void shoot(Actor ship) {
//calculates time passed in milliseconds
if((System.currentTimeMillis() - getLastShotTime()) > T.getShotCoolDown()) {
game.Game.getActors().add(newProjectile(ship));
setLastShotTime(System.currentTimeMillis());
}
}
public String getWeaponName(){
return "" + getClass().getName() + " " + ctor.getName();
}
}
My issue is fairly simple to understand. On the line if((System.currentTimeMillis() - getLastShotTime()) > T.getShotCoolDown())
T is an abstract Projectile class instead of a derived class such as Bullet or Missile so when I call the static method T.getShotDelay() it always calls Projectile.getShotDelay() instead of the derived class.
My only solution is to make an instance of T with ctor and have that attribute be instance based instead of class based, but that seems like a ‘less than ideal’ solution.
I am new to java reflection and am unsure of the syntax to achieve this. I would appreciate any input.
You should use instance methods to get the functionality that you want.
Maybe you should consider using abstract factory pattern.
You can have
IProjectileFactoryinterface that is implemented byMissileFactoryandBulletFactory.The factories are able to create new projectiles
MissileandBulletthat implement theIProjectileinterface. The projectile factories are given as parameters when you create new weapon instances (i.e.new TwinLinkedWeapon(new MissileFactory())).