一、先理解"多态"字面意思
多态 = 多种形态。同一个行为(比如"吃饭"),不同对象做出来有不同的样子。
二、基于继承的多态(用父类引用指向子类对象)
生活例子: 你在宠物店工作,老板说"你去喂一下所有动物"。
- 动物是一个父类(泛指)。
- 猫、狗、鸟是子类。
你的代码只需要用"动物"这个类型去调用"吃东西"方法,至于猫是吃鱼、狗是吃骨头,那是每个子类自己的事。
Java 模拟:
java
Animal a1 = new Cat(); // 父类引用指向子类对象
Animal a2 = new Dog();
a1.eat(); // 输出:猫吃鱼
a2.eat(); // 输出:狗吃骨头
- 变量
a1的类型是Animal,但实际对象是Cat。 eat()方法的具体行为由真实对象决定,而不是变量类型。- 这就是继承多态:父类引用 + 子类重写方法。
关键点: 只要这些对象都是 Animal 的子类,就可以统一处理,各自表现不同。
三、基于接口的多态(用接口引用指向实现类对象)
生活例子: 你不是按"动物"来归类,而是按"能飞"这个能力(接口)。
- 鸟能飞,飞机也能飞,超人也能飞。
他们不是一个父类继承来的,但都实现了"飞"这个接口。
Java 模拟:
java
interface Flyable {
void fly();
}
class Bird implements Flyable {
public void fly() { System.out.println("扇翅膀飞"); }
}
class Airplane implements Flyable {
public void fly() { System.out.println("喷气飞行"); }
}
// 多态使用
Flyable f1 = new Bird();
Flyable f2 = new Airplane();
f1.fly(); // 扇翅膀飞
f2.fly(); // 喷气飞行
Flyable只是定义了"能飞"这个契约(方法签名)。- 任何实现了
Flyable的类都可以被Flyable类型的变量引用。 - 调
fly()时,实际执行的是各自实现类的具体逻辑。
关键点: 继承要求"是某一种类",接口只要求"拥有某种能力"。所以接口更灵活。
四、区别与联系
| 维度 | 继承多态 | 接口多态 |
|---|---|---|
| 关系 | is-a 关系(猫是一种动物) | can-do 关系(鸟能飞) |
| 代码复用 | 可以复用父类代码 | 接口不提供实现,全靠实现类 |
| 灵活性 | 单继承,只能沿一条家谱 | 一个类可实现多个接口,自由组合 |
| 适用场景 | 强关联的类层次结构 | 不同类但需要相同行为 |
五、一句话记住
多态就是:我不管你具体是谁,只要你是这个家族(继承)或者有这个能力(接口),我就用同一个方式调用你,你会自动按你的方式去执行。
- 继承多态:爸爸喊吃饭,每个孩子吃自己的饭
- 接口多态:只要你有"播放"这个功能(MP3、手机、电视),按一下播放键他就自己工作
多在代码里写几遍 父类 变量 = new 子类(); 然后调用方法,看结果是不是子类的行为。写两三个例子就通了。