Python需继承abc.ABC并用@abstractmethod装饰方法才能定义抽象类;Java要求含抽象方法的类必须声明abstract且方法无实现;TS依赖编译时检查,需abstract关键字且方法不可有函数体。

Python 中用 abc.ABC 和 @abstractmethod 声明抽象类
Python 没有关键字如 abstract class,必须靠 abc 模块显式标记。不继承 ABC 或不加 @abstractmethod 装饰器,类就能被实例化,起不到约束作用。
常见错误是只加了 @abstractmethod 但忘了让类继承 ABC,结果子类不实现方法也不会报错;或者把装饰器加在普通函数上,而非方法定义处。
- 必须从
abc.ABC继承,否则抽象方法形同虚设 -
@abstractmethod必须直接写在方法定义上方,不能写在def之后或缩进错位 - 抽象方法里只能写
pass、...或 raiseNotImplementedError,不能有实际逻辑
from abc import ABC, abstractmethod
class PaymentProcessor(ABC):
@abstractmethod
def process(self, amount: float) -> bool:
pass
Java 抽象方法必须用 abstract 修饰且无方法体
Java 要求更严格:只要类里有一个抽象方法,类就必须声明为 abstract;反过来,抽象类可以没有抽象方法,但那样就失去了设计意义。
容易踩的坑是给抽象方法写了大括号和内容(哪怕只有一行),编译直接报错 abstract methods cannot have a body;或者在抽象类里漏掉 abstract 关键字,导致子类不强制重写。
- 抽象方法签名后直接跟分号,不能有
{} - 抽象类本身不能被
new实例化,否则编译失败 - 子类要么实现所有抽象方法,要么自己也声明为
abstract
abstract class NotificationService {
public abstract void send(String message); // ✅ 正确
// public abstract void log() { } // ❌ 编译错误:不能有方法体
}
TypeScript 的抽象类依赖 abstract 关键字和 abstract 方法修饰
TypeScript 是编译时检查,运行时不保留抽象信息。所以它不像 Python 或 Java 那样能阻止实例化——如果只靠类型系统,new 一个抽象类不会报运行时错误,只有在 tsconfig 开启 strict 模式下才可能捕获。
真正起约束作用的是编译阶段:子类未实现抽象方法会报错 Non-abstract class 'X' does not implement inherited abstract member 'Y'。
- 抽象类必须用
abstract声明,抽象方法也必须用abstract修饰 - 抽象方法不能有函数体,连
{}都不能有,否则 TS 编译报错 - 构造函数里可以调用抽象方法,但运行时若子类未正确覆盖,会调用到
undefined
abstract class DataFetcher {
abstract fetch(): Promise<any>; // ✅ 正确
// abstract parse() { } // ❌ TS2515:抽象方法不能有实现
}
抽象方法没实现时的典型报错与排查路径
不同语言触发时机不同:Python 在实例化时抛 TypeError: Can't instantiate abstract class;Java 在编译时报错;TS 在编译时报错,但运行时可能静默失败。
最容易被忽略的是“看似实现了,实则签名不匹配”:比如参数名不同、可选参数位置不对、返回类型不协变,都可能导致子类方法不被识别为实现。
- Python:检查是否漏掉
self参数,或用了@staticmethod/@classmethod却没在抽象方法上对应标注 - Java:检查方法名、参数类型(不是名称)、返回类型是否完全一致,泛型擦除后是否仍匹配
- TypeScript:启用
noImplicitOverride编译选项,强制子类用override显式声明,避免拼写/签名偏差
抽象的本质不是语法糖,而是契约。一旦约定接口,就要确保子类真能按约定响应——这点在多层继承或组合使用时尤其容易滑脱。

















