多态通过父类或接口类型接收子类对象提升扩展性,方法不依赖具体实现而只关注行为契约,新增子类无需修改原有方法签名与调用逻辑,真正实现“对扩展开放、对修改关闭”。

多态在方法参数传递中提升扩展性,核心在于“用父类或接口类型接收子类对象”,让方法不依赖具体实现,只关注行为契约。新增子类时,原有方法签名和调用逻辑完全不用改,真正实现“对扩展开放、对修改关闭”。
用抽象类型定义参数,屏蔽具体实现
方法声明时使用抽象类或接口作为参数类型,而不是某个具体子类。这样调用方传入任意符合该类型的对象,方法内部都可通过统一入口触发对应实现。
- 例如:
void process(Animal animal)比void process(Dog dog)更灵活;后续加Cat、Bird都能直接传入,无需重载或修改方法 - 编译器会强制新类实现必需方法(如
makeSound()),避免漏写导致运行时报错 - 所有业务逻辑(日志、校验、统计)都集中在这个参数入口,不会因类型判断散落在各处
避免 instanceof + if/else 分支蔓延
不用在方法里写一堆 if (obj instanceof Dog) 判断,这种写法每次加新类型都要打开原方法补分支,容易遗漏、难测试、无法编译检查。
- 比如序列化模块原来只支持
Dog和Cat,若用类型判断,加Bird就得找到所有类似代码块挨个补 - 而用多态参数,只需让
Bird实现Serializable或自定义的serialize()接口方法,调用点一行不动 - 分散的类型判断还会导致同一逻辑在多个类里重复,违背单一职责
配合工厂或集合批量处理,扩展更自然
当方法接收的是抽象类型集合(如 List<Shape>),新增图形类型后,只需构造新实例加入列表,主流程无需改动。
立即学习“Java免费学习笔记(深入)”;
-
drawShapes(List<Shape> shapes)可同时处理Circle、Rectangle、未来加的Triangle,循环体内始终调用s.draw() - 如果某子类需要特殊初始化(如带品牌字段的
Vehicle),可用抽象类封装共性构造逻辑,子类复用而不重复写 - 结合泛型与通配符(如
process(List<? extends Animal>)),还能进一步放宽输入范围
注意多态生效的前提条件
不是写了继承就自动多态。只有满足以下条件,参数传入后才能真正调用子类重写的方法:
- 方法必须是非静态、非私有、非 final 的实例方法
- 子类方法签名(名称+参数类型+返回类型)要严格匹配父类/接口定义
- 推荐显式添加
@Override注解,防止拼写错误导致静默调用父类默认逻辑 - 访问字段不走多态——
animal.name读取的是声明类型(如Animal)的字段,不是运行时对象的实际字段


















