3.5 继承
Android游戏开发详解
在设计对象的分类的时候,你可能会发现另一种叫作继承(inheritance)的模式,它给了我们更多的控制权。继承描述了这样一种现象,一个类继承了另一个类中的变量和方法。在这种情况下,继承者称为子类(subclass,或孩子类),而祖先称作超类(superclass,或者父类)。
使用继承比使用接口的优点在于,可以具备复用代码的能力。还记得吧,实现了一个接口的每一个类,都必须针对接口中声明的每一个抽象方法提供一个完整的实现。使用前面小节的例子,这意味着,King、Villain、Professor和SushiChef,都必须拥有它们自己的eat()、walk()和urinate()方法。在这种情况下,继承很强大,因为它允许相似的类共享方法和变量。我们将使用一个假想的角色扮演游戏的例子来说明这一点。
在创建一款角色扮演游戏的时候,你可能有一个名为Hero的类来表示玩家角色,如程序清单3.10所示。
程序清单3.10 Hero类
01 public class Hero {
02 protected int health = 10; // We will discuss ‘protected’ later in this section
03 protected int power = 5;
04 protected int armor = 3;
05
06 public void drinkPotion(Potion p) {
07 health += p.volume(); // Equivalent to health = health + p.volume();
08 }
09
10 public void takeDamage(int damage) {
11 int realDamage = damage - armor;
12 if (realDamage > 0) {
13 health -= realDamage; // Equivalent to health = health – realDamage.
14 }
15 }
16
17 // ... more methods
18
19 }
在创建了Hero之后,你随后决定要让自己的RPG和竞争者有所区分,那就实现一个独特的类系统,其中玩家能够在此前没有见过的Warrior、Mage和Rogue类之间做出选择。
接下来,和任何值得尊敬的面向对象程序员会做的一样,你为每一种角色类型创建了一个单独的Java类,因为Warrior、Mage和Rogue中的每一个都应该具有无法想象的强大而独特的能力。你还决定,既然所有的角色类都是泛型的Hero类的第一个和最重要的扩展,它们每一个都应该拥有程序清单3.10中的Hero类的所有变量和方法。这就是继承的用武之地。
来看一下程序清单3.11到程序清单3.13。
程序清单3.11 Warrior类
public class Warrior extends Hero {
// ... other variables and methods
public void shieldBash() {
...
}
}
程序清单3.12 Mage类
public class Mage extends Hero {
// ... other variables and methods
public void useMagic() {
...
}
}
程序清单3.13 Rogue类
public class Rogue extends Hero {
// ... other variables and methods
public void pickPocket() {
...
}
}
注意,我们使用关键字extends表示继承。这是合适的,因为所有这3个类都是超类Hero的扩展。在继承中,每个子类都针对超类中的所有非私有的变量和方法,接受它们自己的版本(程序清单3.10中的protected变量,类似于private变量,因为外部类是无法访问它们的;然而,和private变量不同,在继承中,子类是可以访问它们的)。
在应用多态的时候,继承的好处最明显,多态允许我们在如下所示的一个方法中使用Hero的任何子类。
// Will attack any Hero regardless of Class
public void attackHero(Hero h, int monsterDamage) {
h.takeDamage(monsterDamage);
}