dimanche 15 février 2015

Enforcing type safety of inherited members in inherited classes

I’m trying to adhere to good OO design principles and design patterns and such. So while developing this C# application of mine I can often find multiple solutions to design and architecture issues, I always want to find and implement the more “canonical” one in the hopes of building highly maintainable and flexible software and also become a better OO programmer.


So suppose I have these two abstract classes: Character and Weapon.



abstract class Weapon
{
public string Name { get; set; }
}

abstract class Character
{
public Weapon weapon { get; set; }
}


Derived classes might be Sword and Staff from Weapon, and Warrior and Mage from Character, etc. (this is all hypothetical, not related to my actual software!).


Every Character has a Weapon, but for every implementation of Character I know what implementation of Weapon it will have. For instance, I know (and I want to enforce!) that at runtime every instance of Warrior will have a Weapon of type Sword. Of course I could do this:



class Sword : Weapon
{
public void Draw() { }
}

class Warrior : Character
{
public Warrior()
{
weapon = new Sword();
}
}


But this way, every time I want to use my Weapon object properly inside a Warrior, I have to perform a cast, which I believe to be a not so great of a practice. Also I have no means to prevent myself from messing up, that is, there is no type safety!


An ideal solution would be to be able to override the Weapon weapon property in the Warrior class with a Sword weapon property, that way I have type safety and if the user uses my Warrior as a Character, he can still use my Sword as a Weapon. Sadly, it doesn’t seem like C# supports this kind of construct.


So here are my questions: is this some kind of classical OO problem, with a name and a well-documented solution? In that case I would very much like to know the name of the problem and the solutions. Some links to good reading material would be very helpful! If not, what kind of class design would you propose in order to maintain functionality and enforce type safety in an elegant and idiomatic way?


Thanks for reading!


Aucun commentaire:

Enregistrer un commentaire