Reputation: 25267
I have the following Classes:
public abstract class Gear<T> : ScriptableObject, IGear { ... }
public class Armor : Gear<ArmorStatsLevel> { ... }
public class Weapon : Gear<WeaponStatsLevel> { ... }
Now I had the following methods to list my instances:
public abstract class WidgetListArmor {
public void ActionSelected(Armor gear) {
if (...) GameSession.Equip(gear);
}
}
public abstract class WidgetListWeapon {
public void ActionSelected(Weapon gear) {
if (...) GameSession.Equip(gear);
}
}
Because this was kind of redundant, I thought of moving it all to a base clase:
public abstract class WidgetListGear<T> : MonoBehaviour {
public void ActionSelected(T gear) {
if (...) GameSession.Equip(gear);
}
}
public class WidgetListArmors : WidgetListGear<Armor> { ... }
public class WidgetListWeapons : WidgetListGear<Weapon> { ... }
And while this seems cleaner, I have a new problem now. Because T is a Generic, GameSession.Equip
can't overload gear
.
Did I chose a bad pattern to organize my code? Am I missing something from Generics that allows me to do this operation?
UPDATE
Here is the GameSession signatures:
public class GameSession {
public static bool Equip(Armor armor);
public static bool Equip(Weapon weapon);
}
Upvotes: 0
Views: 69
Reputation: 1057
What you're looking for is dynamic dispatch. I would suggest you try the following:
GameSession.Equip((dynamic)gear);
However, I don't think it's the best idea since you've tried to encode your Game rules in type system and right now you're starting a mini-compiler in runtime to perform a dispatch for you.
I'd like to point you to Eric Lippert's articles on that subject. Looks like you have similar issues with what he's described.
Part 4 describes the dynamic approach I've provided as well as its disadvantages. Part 5 provides a completely different approach. Overall, I highly recommend reading each part.
Upvotes: 1
Reputation: 118947
Make Weapon
and Armor
implement an interface called IGear
, for example:
public interface IGear
{ }
public class Weapon : IGear
{
//snip
}
public class Armor : IGear
{
//snip
}
Constrain the generic type to IGear
:
public abstract class WidgetListGear<T> : MonoBehaviour
where T : IGear
{
public void ActionSelected(T gear) {
if (...) GameSession.Equip(gear);
}
}
And make GameSession.Equip
take IGear
as the parameter type.
Upvotes: 3