In a method that takes an interface, how could I make the method take any interface's derived interface?

Viewed 50

So I have an interface relationship like this:

public interface IPlayer {
    public List<Card> LoseCards();
}

public interface IPlayer_WithPersonalDeck : IPlayer {
    public void AddCardsToPersonalDeck(List<Card>);
}

I also have a generic command interface that is inherited to command players

public interface ICommands<T> {
    public Object? execute (T)
    public Object? execute (T, T);
}

public class BasePlayerCommands : ICommands<IPlayer> {
    public virtual Object? execute (IPlayer) { throw new NotSupportedException(); }
    public virtual Object? execute (IPlayer executor, IPlayer target) { throw new NotSupportedException(); } 
}

I want to do something like this:

public class TakeCardsFromPlayer_AndAddToDeckCommand : BasePlayerCommands {
    public override List<Card> execute(IPlayer_WithPersonalDeck executor, IPlayer target) {
        return executor.AddCardsToPersonalDeck(target.LoseCards());
    }
}

This does not work as TakeCardsFromPlayer_AndAddToDeckCommand does not find a suitable execute method to overload. Obviously this is because I am using IPlayer_WithPersonalDeck instead IPlayer. However, since that interface derives from IPlayer, why can't I substitute it in?

Doesn't this follow the Liskov Principle, since any class that implements IPlayer_WithPersonalDeck means they are also an IPlayer?

So to me, execute() shouldn't care that it's a derived interface since it shares a base interface of IPlayer like it requires.

Any explanation as to why this doesn't work as I thought would be appreciated, as well as how I can work around this problem.

I would like to avoid having to implement a class that uses ICommand<IPlayer_WithPersonalDeck> as not all my commands may need both players to have a deck, if that's possible.

A solution I have right now is to cast an IPlayer to the correct interface inside of execute. Its unsafe though as any IPlayer could be passed to it and can throw errors if the user isn't careful as not every player has a deck.

0 Answers
Related