封装和继承是协同配合的设计手段:封装划清类职责边界,继承建立语义清晰的“is-a”关系;先用封装确保各实体独立稳定,再在确有共性时轻量使用继承,避免过度设计。

封装和继承不是先后关系,而是协同配合的设计手段:封装决定“每个类怎么管好自己”,继承决定“哪些类之间能自然共享”。真正复杂的类结构,靠的是先用封装把职责切清楚,再用继承把共性串起来。
先用封装划清边界,再用继承建立联系
设计复杂系统时,别一上来就想着“谁继承谁”。先问:这个业务里有哪些独立的、有明确职责的实体?比如电商系统里的订单、支付单、物流单——它们各自状态不同、规则不同、生命周期也不同。每个都该是一个封装完整的类:
- 用private隐藏内部字段(如订单的status、items列表)
- 只暴露必要的方法(如
confirm()、cancel()),并在方法里做校验和状态约束 - 不对外暴露原始集合引用,避免外部绕过逻辑直接修改
等这些核心类各自稳住了,再看它们之间有没有天然的“is-a”关系。比如国际订单和国内订单都是订单的一种,这时才引入继承——让它们共同继承自Order基类,复用通用字段(orderNo、createTime)和基础行为(getTotalAmount()),同时各自重写特殊逻辑(如运费计算、报关处理)。
继承要服务于可维护性,不是为了复用而复用
很多人误以为“有重复代码就该抽父类”,结果抽出一个大而空的BaseEntity,里面塞满无意义的id、createTime、updateTime,反而让子类更难理解。健康的继承结构应满足:
- 子类确实是父类的一种(语义成立),比如
AdminUser是User,但OrderService不是User - 父类提供的是真正通用的行为,而不是“所有类都要有”的模板字段
- 父类不依赖子类的具体实现(避免在父类构造器或方法中调用
abstract或overridden方法) - 层级不超过三层(如
Animal → Mammal → Dog合理,再加一层DomesticDog就容易过度设计)
封装为继承兜底:父类内部细节对子类透明
继承之后,子类不能随意破坏父类的封装契约。例如父类BankAccount把balance设为private,并只通过deposit()和withdraw()控制变更——那子类SavingsAccount就不能绕过这些方法,直接去改balance字段。它只能:
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
- 调用
super.deposit()复用校验逻辑 - 在
withdraw()里增加额外规则(比如每日取款上限),但不跳过原有校验 - 新增自己的封装属性(如
interestRate),仍用private+getter/setter管理
这样,即使未来父类内部把余额从double改成BigDecimal或引入账户冻结状态,只要接口不变,所有子类完全不受影响。
实战中的典型结构:分层封装 + 有限继承
一个稳健的业务模块常这样组织:
-
领域模型层:每个实体类(
Product、Customer)严格封装,字段私有,业务方法内聚 -
公共基类层(可选):仅当多个实体存在真实共性时,才提取如
VersionedEntity(含version、createdAt)或Auditable(含createdBy、lastModifiedBy) -
服务/策略层:用组合代替深层继承,比如
OrderProcessor持有PaymentStrategy和ShippingPolicy接口,而非让各种处理器去继承同一个抽象类
这种结构下,封装保证每个类可独立演进,继承只在语义清晰、复用价值高的地方轻量使用,整体既灵活又可控。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










