簡體   English   中英

C#:調用通過另一個抽象類實現的抽象類方法

[英]C#: Calling an abstract class method which is implemented through another abstract class

我正在用C#創建紙牌游戲。

我有一個抽象類“ Card”:

 public abstract class Card
    {

    }

僅用於提供普通父母(即:公爵是卡,船長也是卡)

以下抽象子類繼承自Card,並用於進一步指定Card的類型(即:Assasin是targetCard,duke是moneycard),每個抽象子類都包含一個名為“ Action”的抽象方法,該抽象方法具有與自身相關的參數: MoneyCard具有抽象方法,該抽象方法將Player和ChipStack作為參數,TargetCard具有抽象方法,將Player和TargetPlayer等作為輸入。

public abstract class PassiveCard : Card
    {
        public abstract void Action();
    }

    public abstract class DeckInteractionCard : Card
    {
        public abstract void Action(Player player, Deck deck);
    }

    public abstract class MoneyCard : Card
    {
        public abstract void Action(Player player, ChipStack chipStack);
    }

    public abstract class TargetCard : Card
    {
        public abstract void Action(Player player, Player targetPlayer);
    }

之后,我將對每種類型的卡進行具體的實現。 它們每個都繼承自上面提到的與自己相關的抽象類之一。

當然,每張卡還完全實現了從其父Abstract-class獲得的abstract方法。

class Duke : MoneyCard
    {
        public override void Action(Player player, ChipStack chipStack)
        {
            for (int i = 0; i < 3; i++)
            {
                player.TakeChip(chipStack);
            }
        }

        public override string ToString()
        {
            return "Duke";
        }
    }


    class Captain : TargetCard
    {
        //this card gives passive protection: how do we do this
        public override void Action(Player player, Player targetPlayer)
        {
           if (targetPlayer.PlayerChips.Count >= 2)
           {
                targetPlayer.GiveChip(2, player);
           }
        }

        public override string ToString()
        {
            return "Captain";
        }
    }


    class Contessa : PassiveCard
    {
        //this card gives passive protection: how do we do this:
        //give the receiving player the option to bluff, show that he really has a contessa, or deny the other having an assasin
        public override void Action()
        {
            throw new NotImplementedException();
        }

        public override string ToString()
        {
            return "Contessa";
        }
    }


    class Ambassador : DeckInteractionCard
    {
        //this card gives passive protection: how do we do this
        public override void Action(Player player, Deck deck)
        {
            //open dialog: which 2 cards would you like to keep?
            //(now, this action just doubles the players hand)
            for (int i = 0; i < 2; i++)
            {
                player.PlayerHand.HandContent.Add(deck.DrawCard());
            }
        }
        public override string ToString()
        {
            return "Ambassador";
        }
    }


    class Assassin : TargetCard
    {
        public override void Action(Player player, Player targetPlayer)
        {
            if (player.PlayerChips.Count >= 3 && targetPlayer.FoldedAllCards == false)
            {
                for (int i = 0; i < 3; i++)
                {
                    player.PlayerChips.RemoveAt(player.PlayerChips.Count - 1);
                }
                targetPlayer.FoldCard();
            }
        }

        public override string ToString()
        {
            return "Assassin";
        }
    }

現在針對我的實際問題:

我有一個Player課。 我要在播放器類中創建一個方法,該方法將通用的“紙牌”作為輸入,然后調用與該特定類型的“紙牌”相關的操作方法卡。 像這樣:

public void CardAction(Card card)
        {
            card.Action();
        }

上面的示例不起作用:編譯器抱怨Abstract類Card沒有稱為action的方法(這很有意義)

因此:我將如何創建一個將通用Card作為輸入並調用與我們作為輸入提供的SPECIFIC卡相關的SPECIFIC Action()方法的方法?

提前致謝,

羅伯特

我認為您的Action方法過於籠統,但是您可以使其起作用。

而不是對Action進行多個簽名,而只使一個僅接收一個參數Context簽名。 在此參數中,放入操作的不同實現可能需要的所有內容。 這是示例:

public class Context
{
    public Player Player;
    public Player TargetPlayer;
    public ChipStack ChipStack;
    ...
}

public abstract class Card
{
    public abstract void Action(Context c);
}

...

public class Duke : MoneyCard
{
    public override void Action(Context c)
    {
        for (int i = 0; i < 3; i++)
        {
            c.Player.TakeChip(c.ChipStack);
        }
    }

    public override string ToString()
    {
        return "Duke";
    }
}

public void CardAction(Card card)
{
    var c = new Context { Player = p1, TargetPlayer = p2, ChipStack = chips };
    card.Action(c);
}

我在這里看到兩個解決方案:您可以檢查每種卡的類型,然后調用適當的方法:

var pCard = card as PassiveCard;
if(pCard != null)
{
    pCard.Action();
    return;
}
var diCard = card as DeckInteractionCard;
if(diCard != null)
{
    diCard.Action(player, deck);
    return;
}
var mCard = card as MoneyCard;
if(mCard != null)
{
    diCard.Action(player, chipStack);
    return;
}
var tCard = card as TargetCard;
if(tCard != null)
{
    tCard.Action(player, targetPlayer);
    return;
}

或者,您可以為Card類提供一個包含所有可能參數的抽象方法:

public abstract class Card
{
    public abstract void Action(Player player, Player targetPlayer, Deck deck, ChipStack chipStack);
}

然后只需實現此方法,並忽略不必要的參數即可。 或者,如果您不希望此方法可見(僅顯示具有必需參數的方法),則可以使基類成​​為接口並進行顯式實現。

public abstract class PassiveCard : Card
{
    public abstract void Action();

    public override void Action(Player player, Player targetPlayer, Deck deck, ChipStack chipStack)
    {
        Action();
    }
}

public abstract class DeckInteractionCard : Card
{
    public abstract void Action(Player player, Deck deck);

    public override void Action(Player player, Player targetPlayer, Deck deck, ChipStack chipStack)
    {
        Action(player, deck);
    }
}

等等

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM