Suppose I have the following interface and implementation:
interface Weapon{
int attack();
}
public class Sword implements Weapon {
//Constructor, and Weapon interface implementation
//...
public void wipeBloodfromSword(){}
}
public class ChargeGun implements Weapon {
//Constructor, and Weapon interface implementation
//...
public void adjustlasersight(){}
}
and Store them like this:
List<Weapon> weaponInventory = new ArrayList<Weapon>();
weaponInventory.add(new Sword());
weaponInventory.add(new ChargeGun());
Problem:
Given that they're stored in the List<Weapon>
I obviously only have access to the methods declared in the Weapon
interface
. If
downcasting
and the use of instanceof/getClass()
should be avoided, how would I get access the the class specific methods wipeBloodfromSword()
and
adjustlasersight()
?
Possible Solution:
Given that there are actions before and after the attack method is called, I can re-write my interface like this:
interface Weapon{
//Can reload a weapon, adjust a laser sight
//do anything to the weapon to prepare for an attack
void prepareWeapon();
int attack();
//Not sure of a more proper name,
//but you can wipe blood off sword or take off silencer
void postAttackActions();
}
While, I'm in control of this hobby project, I might run into a situation where I'm unable to change the interface
, while the interface
re-write may solve this specific problem, what should I do if I have to leave the interface
as is?
Since you have a fixed set of classes, you could use the visitor pattern, which works without explicit downcasts.
class WeaponVisitor {
void visit(Sword aSword) { }
void visit(ChargeGun aGun) { }
}
// add accept method to your Weapon interface
interface Weapon {
...
void accept(Visitor v);
}
// then implement accept in your implementing classes
class Sword {
...
@Override
void accept(Visitor v) {
v.visit(this); // this is instanceof Sword so the right visit method will be picked
}
}
// lastly, extend Visitor and override the methods you are interested in
class OnlySwordVisitor extends Visitor {
@Override void visit(Sword aSword) {
System.out.println("Found a sword!");
aSword.wipeBloodfromSword();
}
}