c#抽象继承设计问题

时间:2011-05-31 18:23:57

标签: c# inheritance abstract

我对C#有些新意,并且我正在努力做好OO原则并编写好的代码。在花了几个小时寻找我的问题后,我发现了一些模糊的答案,但没有什么足够让我有信心。我很有可能会提出一个愚蠢的问题并从错误的角度处理这个问题。

我的问题是:假设我想创建一个抽象的基础卡类,我可以从中编写任何纸牌游戏(例如,让我们比较基本的扑克牌和Magic:The Gathering)。在此之后:http://sourcemaking.com/refactoring/replace-type-code-with-class,我能够创建一个PokerCardType,它基本上是标准套牌中每张卡的美化枚举。我的问题源于如何创建一个抽象的Card类,其中需要一个CardType实例,但是没有确定具体的实例。我的第一个想法是创建一个抽象的CardType类,它有一些方法需要一组静态CardType对象,无论子类是什么,但我无法弄清楚如何做到这一点。我的另一个问题是,这个想法是否真的有意义,或者我应该制作两个独立的类结构,一个用于扑克,一个用于魔术。如果你想知道我为什么要这样做,那真的只是为了我自己的教育。感谢您提供的帮助或任何链接。

6 个答案:

答案 0 :(得分:3)

在我看来,你走错了路。遵循OO原则和编写好的代码有一些重叠,但是没有办法相同。不要试图遵循OO原则,因为有人告诉过你。跟随他们,因为他们符合您解决实际问题的需要。通常的Shape-> Circle / Rectangle /...-& gt; Draw示例只是不公开的,让人很困惑。

很难总结,但我会尝试:要实现一些抽象类,你需要一个很好的抽象。像“卡”这样的东西不是抽象。抽象将是您可以使用卡执行的操作。这些操作显然取决于上下文,因此在不同的上下文(程序)中,您可能会对“卡”的不同抽象方法有所不同。

如果是为了你的教育:实施一个没有任何花哨的OO东西的扑克游戏。然后在没有任何花哨的OO的情况下实现Magic。看看他们有什么共同点。尽量删除尽可能多的重复。现在你会发现一些OO原则非常有用。而且卡片的抽象会自动发展。

答案 1 :(得分:2)

你在这里过度抽象。除非你正在设计一个非常普通的纸牌游戏引擎(我的意思是极端),否则我看不出任何理由为什么一副扑克牌和一副魔术卡可以被认为是“是某个抽象类Deck的{​​{1}}“。

从最简单的工作开始吧。

Deck

如果稍后您发现它们有足够的共同点来提取抽象基类class PokerDeck { } class MagicDeck { } ,那么就这样做。我的观点是,你很可能会发现这种情况。你当然可以尝试,但它可能只是一个精神手淫的巨大运动,收益甚微。

注意:继承很容易成为最容易被误解和误用的OOP概念。

答案 2 :(得分:1)

这是一个抽象类Deck的示例,具有PokerDeck和MagicDeck的特定实现。正如其他人所说,我不确定这是最好的例子,因为游戏之间确实没有太多的共性。

也许如果你做过像Hand with SpadesHand,HeartsHand,PinochleHand,PresidentsHand这样你会在每只手中拥有各种各样的牌。每个游戏都有一个“PlayNextCard”的方法,它们有不同的规则,但都围绕着将手中的牌放在一个共同的堆上。

public abstract class Deck
    {
          public int NumberOfCards{get; private set;}

          public IEnumerable<Card> Cards {get; private set;}

          public void Shuffle()
          {
              Cards = RandomizeCards();
          }

          protected abstract IEnumerable<Card> CreateCardList();

    }

    public class PokerDeck
    {
         public PokerDeck()
         {
              NumberOfCards = 52;
              Cards = CreateCardList();
         }
    }

    public class MagicDeck
    {
         public MagicDeck()
         {
             NumberOfCards = 10000; // have no idea
              Cards = CreateCardList();
         }
    }

然后在每个具体类上实现CreateCardList。所以扑克有2-A的心,黑桃,俱乐部和钻石。魔术有任何神奇的套牌。

您不必实现Shuffle方法,因为它是在基类中执行的。

答案 3 :(得分:0)

听起来你想拥有一个静态CardType类,可以使用你想要支持的一组Card实例来定义它。如果这对你来说不够动态,它仍然可以是一个静态类,它知道所有已经注册的卡片类型。

答案 4 :(得分:0)

我会进一步打破这些要求。你想用基类代表扑克和魔术的牌是什么?除了具有高度和宽度尺寸之外,就它们在各自的游戏中如何使用它们而言它们共享很少的共同点。扑克牌无法点击。魔术牌不能用于组装同花。卡本身并没有做太多。

它们是可以随机播放的,我想......如果你想对它进行建模,你可以创建一个两个类都可以实现的IShuffleable接口。

要直接回答我的想法,你可以用泛型来解决它。假设您想拥有一副牌:

public class CardDeck<T> : where T:BaseCardType
{
   private List<T> _cards new List<T>();

   public void Shuffle()
   {
      // blah blah
   }

   public void SomethingElseYouCanDoWithADeck
   { }
}

我认为你不会为你做太多的事情......你能详细说明一下如何设计这些课程吗?

答案 5 :(得分:0)

抽象类和继承的想法是接近同一个事物的类。通常情况下,子类是“更好定义”或“更具体”的实例,而不仅仅是基本类型。

例如:警车是轿车的更具体版本,因此警车将继承轿车。但是MTG卡不是扑克牌的更具体的例子,反之亦然。你可以为某些纸牌游戏做这件事,比如扑克牌和Uno牌,因为它们有着共同的特征,比如面值和套装/颜色。

相关问题