14.4 发牌
现在可以创建一个 Deck 对象并发牌了。下面是一个简单示例,它将 5 张牌作为玩家手中的牌,并将余下的牌作为储备牌:
Deck deck = new Deck("Deck");deck.shuffle();Hand hand = new Hand("Hand");deck.deal(hand, 5);hand.display();Hand drawPile = new Hand("Draw Pile");deck.dealAll(drawPile);System.out.printf("Draw Pile has %d cards.\n",drawPile.size());
CardCollection 提供了方法 dealAll,这个方法将余下的牌都发出去。这个示例的输出如下:
Hand:5 of DiamondsAce of Hearts6 of Clubs6 of Diamonds2 of ClubsDraw Pile has 47 cards.
当然,如果你运行这个示例,得到的那手牌可能不同,因此整副牌洗得很乱。
如果你很细心,可能注意到了一些怪异的情况。我们再来看一眼方法 deal 的定义:
public void deal(CardCollection that, int n) {for (int i = 0; i < n; i++) {Card card = popCard();that.addCard(card);}}
注意,第一个形参是一个 CardCollection 对象,而我们却以如下方式调用这个方法:
Hand hand = new Hand("Hand");deck.deal(hand, 5);
相应的实参是一个 Hand 对象,而不是 CardCollection 对象。这种做法怎么就合法呢?这是因为 Hand 是 CardCollection 的子类,所以 Hand 对象也被视为 CardCollection 对象。如果方法需要一个 CardCollection 对象,可向它提供一个 Hand、Deck 或 CardCollection 对象。
然而,反过来则不行:并非每个 CardCollection 对象都是 Hand 对象。因此,如果方法需要一个 Hand 对象,你就必须给它提供一个 Hand 对象,而不能给它提供一个 CardCollection 对象。
一个对象可以属于多种类型好像有点怪,但现实世界也存在这样的情况。所有的猫都是哺乳动物,所有哺乳动物都是动物;但并非所有的动物都是哺乳动物,并非所有的哺乳动物都是猫。
