2011-05-31 96 views
3

我对C#有点新,并且试图按照面向对象的原则做好工作并编写出好的代码。花了几个小时寻找我的问题后,我发现了一些模糊的答案,但没有足够的东西让我感到自信。我有一个很好的机会问一个愚蠢的问题,并从错误的角度来解决这个问题。我的问题是:假设我想创建一个抽象的基础卡类,从中我可以组成任何纸牌游戏(例如让我们比较基本的扑克牌和Magic:The Gathering组合)。在此之后:http://sourcemaking.com/refactoring/replace-type-code-with-class,我可以创建一个PokerCardType,它基本上是标准牌组中每张牌的枚举值。我的问题来自于如何创建一个需要CardType实例的抽象Card类,但具体实例未确定。我的第一个想法是创建一个抽象的CardType类,这将有一些需要一组静态CardType对象的任何子类,但我不知道如何做到这一点。我的另一个问题是,这个想法是否真的有意义,还是应该制作两个单独的课程结构,一个用于扑克,另一个用于魔术。如果你想知道为什么我想要这样做,那真的只是为了我自己的教育。感谢您的帮助或您可以提供的任何链接。c#抽象继承设计问题

+1

我会先问一下魔术牌与扑克牌有什么共同的“事物”/属性? – Nix 2011-05-31 18:29:27

+0

你所有的答案基本上都指向同一个想法,Magic和Poker之间是否有足够的共同点来创建一些基础对象,可能不是。在我开始阅读越来越多的内容之前,我认为最好的办法是简单地把他们分开,但很快就在继承的世界中消耗掉了。正如许多人所建议的那样,我会将它们分开。感谢所有的快速回复。他们中的任何一个都可以被认为是正确的答案,但我把它交给泰勒,因为他展示了如果有意义的话你可以做到这一点。再次感谢。 – user778128 2011-05-31 18:42:46

回答

1

下面是一个抽象类Deck的例子,具体实现了PokerDeck和MagicDeck。正如其他人所说,我不确定这是最好的例子,因为游戏之间确实没有很多共同点。

也许如果你做了类似手中的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方法,因为它是在基类中执行的。

0

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

3

我认为你走错了路。遵循面向对象的原则和编写好的代码有相当的重叠,但不是相同的。不要试图遵循面向对象的原则,因为有人告诉过你。跟随他们,因为他们适合你解决一个真正的问题的需要。通常的Shape-> Circle/Rectangle /...-> Draw示例仅仅是无用的,并且让人困惑。

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

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

0

我会进一步打破这些要求。关于扑克和魔术的卡片,你想用基础类来代表什么?除了具有高度和宽度尺寸之外,它们在它们各自的游戏中如何使用它们的共同之处很少。扑克牌不能被挖掘。魔术牌不能用来组装冲水。卡片本身并没有太多的功能。

他们是洗牌能力,我想......如果你想要建模,你可以创建一个两个类都可以实现的易混接口。

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

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

    public void Shuffle() 
    { 
     // blah blah 
    } 

    public void SomethingElseYouCanDoWithADeck 
    { } 
} 

我只是不thinkt Hat的要为你做很多...你能对你将如何使用这些类语焉不详,一旦设计的?

2

你在这里过分抽象。除非你在设计一款非常通用的纸牌游戏引擎(我的意思是非常特别),否则我看不出有什么理由说明一套扑克牌和一副魔术牌可以被认为是“是一个Deck“为一些抽象类Deck

从最简单的工作开始。

class PokerDeck { } 
class MagicDeck { } 

如果以后你发现自己有足够的共同点来提取一个抽象基类Deck,做到这一点呢。我的观点是,你不太可能会发现这种情况。你当然可以尝试,但这可能只是一个巨大的心理手淫练习,收益很少。

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

+0

甲板是一个不好的例子,因为共享功能。 – Nix 2011-05-31 18:36:13

+0

是的,多年后我仍然无法理解何时,以及如何正确使用继承:( – ppumkin 2014-03-27 22:45:53

0

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

例如:警车是轿车的更具体的版本,所以警车会从轿车继承。但MTG卡不是扑克牌的更具体的实例,反之亦然。你可能可以为一些纸牌游戏做这个,比如扑克牌和Uno牌,因为它们具有面值和套装/颜色等共同特征。