Enrique Moreno Tent
Enrique Moreno Tent

Reputation: 25267

Overloading methods while using Generics with base classes

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

Answers (2)

Vlad Stryapko
Vlad Stryapko

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

DavidG
DavidG

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

Related Questions