1. 经典例题
定义一个父类Animal,包含私有属性name、构造方法和普通方法eat();再定义两个子类Dog和Cat,继承自Animal并分别重写eat()方法;最后编写测试类,使用父类引用指向子类对象的方式调用eat()方法,验证多态的执行效果。
要求:
- 父类Animal的eat()方法输出:"动物在吃东西"
- 子类Dog的eat()方法输出:"小狗 [名字] 在啃骨头"
- 子类Cat的eat()方法输出:"小猫 [名字] 在吃鱼"
- 测试类中创建 3 个对象:一个父类对象、一个 Dog 子类对象、一个 Cat 子类对象,统一用Animal类型引用接收并调用eat()
2. 解题思路
3. 代码实现与逐行解释
java
运行
// 1. 定义父类Animal
public class Animal {
// 私有属性:封装,只能通过父类方法访问
private String name;
// 父类构造方法:初始化name属性
public Animal(String name) {
this.name = name; // this指代当前对象,给当前对象的name赋值
}
// 父类普通方法:所有动物共有的行为
public void eat() {
System.out.println("动物在吃东西");
}
// 提供getter方法,让子类可以获取name属性
public String getName() {
return name;
}
}
// 2. 定义子类Dog,继承Animal
class Dog extends Animal {
// 子类构造方法:必须通过super调用父类构造方法
public Dog(String name) {
super(name); // super指代父类对象,调用父类的构造方法初始化name
}
// 重写父类的eat()方法:@Override注解标记重写
@Override
public void eat() {
// 调用父类的getName()获取名字,实现子类特有行为
System.out.println("小狗" + getName() + "在啃骨头");
}
}
// 3. 定义子类Cat,继承Animal
class Cat extends Animal {
public Cat(String name) {
super(name);
}
@Override
public void eat() {
System.out.println("小猫" + getName() + "在吃鱼");
}
}
// 4. 测试类,验证多态
class TestPolymorphism {
public static void main(String[] args) {
// 父类引用指向父类对象:执行父类的eat()
Animal animal = new Animal("通用动物");
// 父类引用指向Dog子类对象:向上转型,执行Dog的eat()
Animal dog = new Dog("旺财");
// 父类引用指向Cat子类对象:向上转型,执行Cat的eat()
Animal cat = new Cat("咪咪");
// 统一调用eat()方法,实际执行不同子类的逻辑
animal.eat();
dog.eat();
cat.eat();
}
}
运行结果
plaintext
动物在吃东西
小狗旺财在啃骨头
小猫咪咪在吃鱼
4. 核心总结
-
多态的三个必要前提
- 必须有继承关系(子类继承父类)
- 子类必须重写父类的方法
- 必须存在向上转型(父类引用指向子类对象)
-
多态的核心优势
- 提高代码扩展性:新增子类(如Pig)时,无需修改测试类代码,直接继承并重写方法即可
- 统一调用规范:所有子类对象都可以用父类引用接收,调用同一个方法实现不同逻辑
-
常见误区
- 成员变量不参与多态:编译和运行都看左边(父类)
- 静态方法不能被重写:属于类,不属于对象,调用时看引用类型
- 私有方法不能被重写:子类无法访问父类私有方法,重写无效


