is-a关系用抽象类,like-a关系用接口;前者强调本质同一性与状态共享,后者强调行为契约与解耦复用。

“Is-A”和“Like-A”不是语法标签,而是设计时对类与类、类与行为之间关系的直觉判断——它决定了你该用抽象类还是接口。
Is-A:身份归属,强调本质同一性
当你说“A is a B”,意思是A在概念上就是B的一种,天然属于B这个族群。这种关系具有继承的合理性、状态共享的必要性,以及逻辑骨架复用的价值。
- Dog is a Animal → Dog继承Animal抽象类,共享name、age字段,复用sleep()实现,必须重写makeSound()
- MySQLConnection is a DatabaseConnection → 抽象类可封装连接池管理、事务模板等共性逻辑
- PDFExporter is a DocumentExporter → 共有exportHeader()、exportFooter()等流程骨架,子类只定制中间内容
这类场景下,抽象类提供“模板+状态+部分实现”,子类是它的自然延伸,不是临时拼凑的能力组合。
Like-A:能力契约,强调行为一致性
当你说“A is like a B”,意思是A虽不属于B的类别,但当前需要表现出B所约定的行为。它不关心你是谁,只关心你能不能做某件事。
- Drone is like a Flyable → 和Bird、Helicopter无关血缘,但都得实现fly(),接口定义契约即可
- Car is like a Alarmable → 汽车不是报警器,但可以加装报警功能;Alarmable接口让Door、Car、Safe都能响应alarm()
- UserService is like a Cacheable → 业务类本身是服务,但需要缓存能力;用Cacheable接口解耦,不污染核心职责
接口不携带状态,不参与构造,只声明“你得提供这个能力”,实现类自由选择怎么实现,彼此无耦合。
混淆时的关键自问
遇到拿不准的情况,直接问自己三个问题:
- 这些类是不是同一类事物?(比如都是“支付方式”:Alipay、WechatPay、CreditCard → 是,适合抽象类)
- 它们有没有共用的字段或初始化逻辑?(比如都有appId、secretKey、签名算法模板 → 适合抽象类)
- 这个能力会不会被完全不相关的类同时需要?(比如Loggable被Controller、Service、Job都用到 → 适合接口)
答案偏向“是”,往抽象类靠;偏向“否”,就该用接口。设计不是填空题,而是用类型系统讲清楚你心里想表达的关系。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











