python 用抽象基类(abc)或 protocol 实现接口约束,typescript 用 interface + implements;abc 在运行时强制实现,protocol 和 ts interface 仅静态检查。

在类中实现类似接口的约束行为,核心是让类明确承诺提供某些方法或属性,且这些成员必须被具体实现——这在 Python 中没有原生 interface 关键字,但可通过抽象基类(ABC)达成;在 TypeScript 或 Java 等语言中则直接支持接口(interface)或抽象类。
用抽象基类(Python)强制子类实现特定方法
Python 的 abc.ABC 和 @abstractmethod 装饰器可定义“不能被实例化的类”,并要求继承者实现标注的方法:
- 继承
ABC类,声明为抽象基类 - 用
@abstractmethod标记必须重写的方法(包括__init__、普通方法、property 等) - 若子类未实现所有抽象方法,实例化时会报
TypeError
示例:
from abc import ABC, abstractmethod
<p>class Drawable(ABC):
@abstractmethod
def draw(self) -> None:
pass</p><pre class="brush:php;toolbar:false;"><pre class="brush:php;toolbar:false;">@property
@abstractmethod
def area(self) -> float:
passclass Circle(Drawable): def init(self, radius: float): self.radius = radius
def draw(self): # ✅ 必须实现
print("Drawing a circle")
@property
def area(self): # ✅ 必须实现
return 3.14 * self.radius ** 2这样,任何 Drawable
draw 和 area,否则无法创建实例。用协议(Protocol)实现结构化接口(Python 3.8+)
当不需要继承关系,只关心“有没有某几个方法”,可用 typing.Protocol。它不强制继承,仅做类型检查时的鸭子类型约束:
- 定义一个类继承
Protocol,只写方法签名(无需def实现) - 函数参数标注为该 Protocol 类型时,静态类型检查器(如 mypy)会验证传入对象是否具备对应方法
- 运行时不产生任何约束,纯编译期/检查期行为
示例:
from typing import Protocol <p>class Renderable(Protocol): def render(self) -> str: ...</p><p>def show(r: Renderable) -> None: print(r.render())</p><p>class Button: def render(self) -> str: # ✅ 满足 Renderable 结构 return "<button>OK</button>"</p><p>show(Button()) # 类型检查通过,运行正常</p>
在 TypeScript 中用 interface + class implements
TypeScript 提供原生 interface,配合 implements 关键字可强制类满足契约:
-
interface只描述结构(方法名、参数、返回值),不包含实现 -
class X implements Y表示 X 必须提供 Y 中定义的所有成员,否则编译报错 - 支持多个接口,也支持接口继承接口
示例:
interface Logger {
log(message: string): void;
level: 'debug' | 'info' | 'error';
}
<p>class ConsoleLogger implements Logger {
level = 'info'; // ✅ 必须有
log(message: string) { // ✅ 必须有,签名匹配
console.log(<code>[${this.level}] ${message}</code>);
}
}</p>
若漏写 level 或改了 log 参数类型,TS 编译器立刻提示错误。
避免常见误区:抽象类 ≠ 接口,Protocol ≠ runtime 检查
注意几类工具的实际作用边界:
- 抽象基类(
ABC)在运行时起效,但仅限继承场景;它不是“接口”的完全等价物(比如不能多继承多个 ABC) -
Protocol是静态类型工具,对运行无影响;它不阻止你传入不合规对象,只是提醒你可能出错 - TypeScript 的
interface同样只在编译期校验,生成的 JS 不含任何接口信息 - 不要试图用普通基类 +
NotImplementedError模拟接口——它无法在实例化前报错,约束力弱
选择哪种方式,取决于你的语言、是否需要运行时保障、是否接受继承耦合、以及团队协作中的类型安全要求。











