到底该用组合(composition)还是继承(inheritance),一句话结论先给出:
优先使用组合,只有在“is-a”关系非常明确、且需要复用行为而不仅仅是数据时,才考虑继承。
下面从原理、对比、场景和示例几个层面说清楚。
| 维度 | 继承 | 组合 |
|---|---|---|
| 耦合度 | 高(父类变化影响子类) | 低 |
| 灵活性 | 低(编译期绑定) | 高(运行期可替换) |
| 扩展性 | 差(多层继承易爆炸) | 强 |
| 代码复用 | 复用“行为” | 复用“能力” |
| 可测试性 | 较难 | 更容易 |
| 设计原则 | 违反封装倾向 | 更符合封装 |
真的是“is-a”关系
Dog is an Animal
Square is a Shape
你不打算改父类
需要多态
Toolbox extends ArrayList<Tool> ❌
如果只是为了“复用 ArrayList 的方法”,这是错误动机。
class Bird extends Wing {
// Bird 不是 Wing
}
class Bird {
private Wing wing;
}
尽量使用对象组合,而不是继承来达到复用目的
子类必须能完全替代父类
如果做不到,就别继承
class PaymentService {
private PaymentStrategy strategy;
}
而不是:
class AlipayPayment extends PaymentService ❌
当你犹豫时,问自己三句话:
只要有一条是“否”,就选组合。
这是现代工程最常用的方案
interface Flyable {
void fly();
}
class Bird {
private Flyable flyer;
}
✅ 解耦
✅ 可替换
✅ 可测试
✅ 符合开闭原则
继承是“白盒复用”,组合是“黑盒复用”;
能用组合就用组合,继承留给真正的“语义关系”。
如果你愿意,可以贴一段你现在的代码,我可以直接帮你判断:这里该用继承还是组合,以及怎么改最好。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。