2011-05-31 97 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牌,因爲它們具有面值和套裝/顏色等共同特徵。