interface 是可执行的契约,必须被具体类型实现才能通过编译,其核心价值在于倒置依赖与协议对齐;定义需置于调用方可导入的公共包,方法应聚焦业务意图、接口宜小,Java 安全扩展靠新接口而非 default 方法,TS interface 仅编译期存在,运行时校验需 type guard 或 zod 等工具。

interface 不是接口文档,而是可执行的契约——它必须被具体类型实现,否则编译不通过,这才是解耦有效的前提。
Go 中 interface 如何强制模块间协议对齐
在 Go 里,interface 的核心价值不是“定义能力”,而是“倒置依赖”:下游模块(如数据库实现)实现 interface,上游模块(如业务逻辑)只依赖该 interface,不碰具体类型。
常见错误是把 interface 定义在实现包内(比如 db/postgres.go 里定义 Storer),这会导致上游无法提前引用,失去解耦意义。
- 正确做法:将
interface定义在调用方能 import 的公共包中(如domain/port.go或contract/) - 方法签名要聚焦“业务意图”,避免暴露实现细节(例如用
SaveUser(ctx, u User)而非InsertIntoUsersTable(...)) - 接口宜小不宜大:一个
interface最好只含 2–4 个方法;过宽会提高实现成本,且违背“被需要时才实现”的原则
Java 的 interface + default method 怎么安全扩展协议
Java 8+ 允许 interface 添加 default 方法,但直接加新方法会破坏已有实现类——除非它们显式重写或继承了提供默认行为的父类。
真正安全的扩展方式是“兼容性版本控制”:
- 新增功能不修改原
interface,而是定义新interface(如UserRepositoryV2 extends UserRepository) - 旧实现类继续工作;新模块选择实现
V2,老模块不受影响 - 避免滥用
default实现复杂逻辑——它无法访问实现类的私有状态,容易导致“伪扩展”(表面编译通过,运行时行为异常)
示例:UserRepository 原只有 findById(id);扩展分页需求时,不往里面加 findPage(...),而是新建 PagedUserRepository。
TypeScript 的 interface 为何不能直接用于运行时校验
TypeScript 的 interface 是纯编译期概念,会被擦除。这意味着:
- 你无法在运行时用
instanceof或typeof检查某个对象是否“实现了某interface” - 即使两个
interface结构完全一致,也不能互相赋值(除非启用skipLibCheck或使用as强制断言) - 想做运行时协议检查,得靠
type guard函数或第三方库(如zod、io-ts)重新描述结构
典型误用:function handleUser(u: UserInterface) { if (u instanceof UserInterface) {...} } —— 这行不通,UserInterface 在 JS 运行时根本不存在。
interface 的力量不在定义本身,而在于谁来实现、谁来消费、以及何时引入变更。最容易被忽略的是:协议升级必须同步更新测试用例和 mock 实现,否则“解耦”只是编译器眼中的幻觉。

















