I've a simple code base with few 'weapon' concrete classes which implements different contracts in order to be used by its clients.
My contracts:
public interface IWeaponPrimaryAttack
{
void DoAttack();
}
public interface IWeaponSecondaryAttack
{
void DoSecondaryAttack();
}
public interface IReloadable
{
void Reload();
}
Concrete implementation or the actual weapons:
public class Katana : IWeaponPrimaryAttack, IWeaponSecondaryAttack
{
public void DoAttack(){Console.WriteLine ("Swing");}
public void DoSecondaryAttack() {Console.WriteLine ("Stab");}
}
public class ShotGun : IWeaponPrimaryAttack, IReloadable
{
public void DoAttack(){Console.WriteLine ("Swing");}
public void Reload() {//reload it}
}
Clients that uses these concrete classes:
public class PrimaryAttack
{
private IWeaponPrimaryAttack _attack;
public PrimaryAttack(IWeaponPrimaryAttack attack)
{
_attack = attack;
}
public void DoAttack()
{
_attack.DoAttack();
}
}
public class SecondaryAttack
{
private IWeaponSecondaryAttack _attack;
public SecondaryAttack(IWeaponSecondaryAttack attack)
{
_attack = attack;
}
public void DoSecondaryAttack()
{
_attack.DoSecondaryAttack();
}
}
public class WeaponReload
{
private IReloadable _reloader;
public WeaponReload(IReloadable reloader)
{
_reloader = reloader;
}
public void Reload()
{
_reloader.Reload();
}
}
New of course the instantiation of concrete class only be known when the user selects one among many weapons(one among ShotGun, Katana, etc).
Let say the use has selected ShotGun as the weapon, based on the selection it might go like this:
IWeaponPrimaryAttack weapon = new ShotGun(); // get it from a factory
PrimaryAttack primaryAttack = new PrimaryAttack(weapon);
primaryAttack.DoAttack();
Now for the WeaponReload have to do a typecast here in order to use it.
WeaponReload reloader = new WeaponReload ((IReloadable)weapon);
reloader.Reload();
I have questions around it,
- Should I really have to end up typecasting eventually?
- Or there is a better way to handle this object creation part.
- Or there is entirely a better design that I can come up with which does not necessarily ends up in casting.
- Or casting it like this is totally fine.