14.3 继承
至此,我们定义了一个表示扑克牌集合的类,下面用它定义 Deck 和 Hand 类。Deck 类的完整定义如下:
public class Deck extends CardCollection {public Deck(String label) {super(label);for (int suit = 0; suit <= 3; suit++) {for (int rank = 1; rank <= 13; rank++) {cards.add(new Card(rank, suit));}}}}
第 1 行用关键词 extends 指出 Deck 类扩展了 CardCollection 类,这意味着 Deck 对象将包含 CardCollection 对象的所有实例变量和方法。换而言之,Deck“继承”了 CardCollection。我们还可以说 CardCollection 是一个超类(superclass),而 Deck 是其子类。
在 Java 中,类只能扩展一个超类。没有用 extends 指定超类的类将自动继承 java.lang.Object。因此,在这个实例中,Deck 扩展了 CardCollection,而 CardCollection 扩展了 Object。Object 类提供了默认方法 equals 和 toString 等。
构造函数不被继承,但所有其他的公有属性和方法都被继承。到目前为止,Deck 中新增的唯一一个方法是构造函数,因此你可像下面这样创建 Deck 对象:
Deck deck = new Deck("Deck");
Deck 构造函数的第 1 行使用了以前没有介绍过的 super,这是一个关键词,指的是当前类的超类。像这里这样将 super 用作方法时,将调用超类的构造函数。
因此在这里,super 调用 CardCollection 的构造函数,而这个构造函数初始化属性 label 和 cards。这个构造函数返回后,将接着执行 Deck 的构造函数:用 Card 对象填充原本为空的 ArrayList。
这就是 Deck 类。我们还需要表示一手牌和一堆牌,其中前者是玩家手里的扑克牌集合,而后者是桌子上的扑克牌集合。为此,我们可定义两个类,分别用于表示一手牌和一堆牌,但它们的差别不大。因此,我们将用同一个类 Hand 来表示一手牌和一堆牌。这个类的定义类似于下面这样:
public class Hand extends CardCollection {public Hand(String label) {super(label);}public void display() {System.out.println(getLabel() + ": ");for (int i = 0; i < size(); i++) {System.out.println(getCard(i));}System.out.println();}}
与 Deck 一样,Hand 也扩展了 CardCollection,因此它继承了 getLabel、size 和 getCard 等方法,并在方法 display 中使用了这些方法。Hand 也提供了一个构造函数,就只是调用 CardCollection 的构造函数,除此之外什么都没有做。
总之,Deck 类似于 CardCollection,但提供的构造函数不同。且 Hand 也类似于 CardCollection,但提供了一个额外的方法——display。
