Lazy loaded image
[UE]组合/继承的选择
字数 716阅读时长 2 分钟
2026-2-26
2026-2-26
type
Post
status
Published
date
Feb 26, 2026
slug
summary
tags
虚幻
思考
编程
category
学习笔记
comment
Show
icon
password
遵守“Is-A(是一个)”vs“Has-A(有一个)”法则——面向对象编程中的一条基础设计原则

核心概念对比:“Has-A” vs “Is-A”

“Has-A”(有一个)—— 组合

含义:新对象把老对象作为自己的一个“零件”或“属性”装配进来。比如:电脑有一个CPU,电脑有一个打印机。
特点:把任务委托给更专业的部分去完成。

“Is-A”(是一个)—— 继承

含义:子类完全继承父类的基因,是父类的一种特殊形态。比如:苹果是一个水果,汽车是一个交通工具。
特点:子类自动获得父类的所有非私有属性和方法。

组合和继承的优劣

对比维度
“Has-A”(组合/聚合)✅推荐
“Is-A”(继承)⚠️需谨慎
复用类型
黑箱复用:不需要知道内部细节,只管调用接口。
白箱复用:破坏了封装,父类内部细节对子类暴露无遗。
耦合度
:依赖较少,一个零件坏了换一个即可。
:父类一旦修改,所有子类都可能受到牵连(牵一发而动全身)。
灵活性
动态(运行时):可以在程序运行时动态更换或添加零件。
静态(编译时):关系在写代码时就锁死了,无法在运行中改变。
缺点
需要管理的对象数量可能会变多。
极易被滥用,增加系统复杂度和维护难度。

什么时候用“继承”

继承固然强大,但是滥用的副作用也不容小觑,使用时应遵守Coad法则,只有当同时满足以下条件时,才应该使用继承(Is-A):
  • 真的是同类:子类必须是父类的“一种特殊种类”,而不是父类的“一个角色”。
  • 不频繁换爹:子类将来不会变成其他类的子类。
  • 只做加法:子类是为了扩展父类的功能,而不是大量推翻重写(置换)父类的功能。
  • 有现实意义:在现实世界的分类学上是讲得通的(不要仅仅为了借用某个工具类的方法而去继承它)。

经典实际案例:角色陷阱

人们经常犯的错误是把“角色”(Has-A)当成了“种类”(Is-A)
  • 错误设计(滥用继承):把“人”作为父类,“经理”、“雇员”、“学生”作为子类。
    • 矛盾点:这是一种“Is-A”设计。如果一个人既是雇员又是学生呢?如果他升职成了经理呢?由于继承是静态排他的,这种设计会直接崩溃。
notion image
  • 正确设计(使用组合/聚合):创建一个“角色”类(包含经理、雇员等子类),然后让“人”拥有(Has-A)多个“角色”。
    • 优势:一个人可以动态地添加、删除不同的角色,完美契合现实逻辑。
notion image

总结:

📌
当复用代码时,先考虑:这两个类到底是“A包含B(Has-A)”还是“A本质上就是B(Is-A)”?如果是前者,果断用组合;即使是后者,也要慎重评估是否会带来高耦合。

📎 参考文章

上一篇
[UE]重定向引用器
下一篇
专业DJ混音软件

评论
Loading...