1. 什么是抽象类? #

1.1 没有抽象类的问题 #

# 普通父类,方法体为空占位
class Animal:
    def make_sound(self):
        pass

# 子类只实现了 make_sound
class Dog(Animal):
    def make_sound(self):
        return "Woof!"
    # 忘记实现 move(),程序不会报错

# 实例化不会报错
dog = Dog()
# 调用未实现的方法会出错
print(dog.move())

1.2 使用抽象类后 #

# 导入抽象基类和抽象方法装饰器
from abc import ABC, abstractmethod

# 继承 ABC 成为抽象基类
class Animal(ABC):
    # 子类必须实现 make_sound
    @abstractmethod
    def make_sound(self):
        pass

    # 子类必须实现 move
    @abstractmethod
    def move(self):
        pass

# 实现所有抽象方法的子类
class Dog(Animal):
    def make_sound(self):
        return "Woof!"

    def move(self):
        return "Running"

# 缺少 move() 的子类实例化时会报 TypeError
# class Bird(Animal):
#     def make_sound(self):
#         return "Chirp!"

2. 前置知识 #

# 父类,含构造方法
class Animal:
    def __init__(self, name):
        self.name = name

# 子类继承父类
class Dog(Animal):
    def bark(self):
        return f"{self.name} says Woof!"

# 创建子类实例
dog = Dog("旺财")
print(dog.bark())

3. abc 模块 #

# 导入 ABC 和 abstractmethod
from abc import ABC, abstractmethod

4. 基本用法 #

# 导入抽象基类相关组件
from abc import ABC, abstractmethod

# 定义抽象动物类
class Animal(ABC):
    # 抽象方法:子类必须实现
    @abstractmethod
    def make_sound(self):
        """子类必须实现"""
        pass

    # 普通方法:有默认实现
    def sleep(self):
        """普通方法,有默认实现"""
        return "正在睡觉..."

# 子类实现抽象方法
class Dog(Animal):
    def make_sound(self):
        return "Woof!"

# 创建子类实例
dog = Dog()
print(dog.make_sound())
print(dog.sleep())

5. 抽象方法实战:图形系统 #

# 导入抽象基类和数学模块
from abc import ABC, abstractmethod
import math

# 图形抽象基类
class Shape(ABC):
    # 子类必须实现面积计算
    @abstractmethod
    def area(self) -> float:
        pass

    # 子类必须实现周长计算
    @abstractmethod
    def perimeter(self) -> float:
        pass

    # 普通方法,调用抽象 area()
    def describe(self) -> str:
        return f"面积: {self.area():.2f}"

# 矩形实现
class Rectangle(Shape):
    def __init__(self, width: float, height: float):
        self.width = width
        self.height = height

    def area(self) -> float:
        return self.width * self.height

    def perimeter(self) -> float:
        return 2 * (self.width + self.height)

# 圆形实现
class Circle(Shape):
    def __init__(self, radius: float):
        self.radius = radius

    def area(self) -> float:
        return math.pi * self.radius ** 2

    def perimeter(self) -> float:
        return 2 * math.pi * self.radius

# 创建矩形并输出描述
rect = Rectangle(5, 3)
print(rect.describe())

6. 抽象属性 #

# 导入抽象基类相关组件
from abc import ABC, abstractmethod

# 插件抽象基类
class Plugin(ABC):
    # 抽象只读属性 name,@property 必须在 @abstractmethod 之前
    @property
    @abstractmethod
    def name(self) -> str:
        pass

# 具体插件实现 name 属性
class JSONPlugin(Plugin):
    @property
    def name(self) -> str:
        return "json"

7. 实际应用:策略模式 #

# 导入抽象基类相关组件
from abc import ABC, abstractmethod

# 支付策略抽象基类
class PaymentStrategy(ABC):
    @abstractmethod
    def pay(self, amount: float) -> bool:
        pass

# 信用卡支付实现
class CreditCardPayment(PaymentStrategy):
    def __init__(self, card_number: str):
        self.card_number = card_number

    def pay(self, amount: float) -> bool:
        print(f"信用卡 {self.card_number[-4:]} 支付 ${amount}")
        return True

# 支付宝支付实现
class AlipayPayment(PaymentStrategy):
    def __init__(self, account: str):
        self.account = account

    def pay(self, amount: float) -> bool:
        print(f"支付宝 {self.account} 支付 ${amount}")
        return True

# 结账类,依赖抽象策略而非具体实现
class Checkout:
    def __init__(self, strategy: PaymentStrategy):
        self.strategy = strategy

    def pay(self, amount: float) -> bool:
        return self.strategy.pay(amount)

# 使用信用卡策略
checkout = Checkout(CreditCardPayment("1234567890123456"))
checkout.pay(99.99)

# 运行时切换为支付宝策略
checkout = Checkout(AlipayPayment("user@example.com"))
checkout.pay(99.99)

8. 常见错误 #

8.1 忘记实现抽象方法 #

# 未实现任何抽象方法的子类
class Dog(Animal):
    pass

# 实例化时报 TypeError
# dog = Dog()

8.2 装饰器顺序错误 #

# 错误:@abstractmethod 不能在 @property 之前
@abstractmethod
@property
def name(self): ...

# 正确:@property 在前,@abstractmethod 在后
@property
@abstractmethod
def name(self): ...

8.3 直接实例化抽象类 #

# 抽象类不能直接实例化,会报 TypeError
# animal = Animal()

9. 总结 #

9.1 关键写法 #

# 导入抽象基类相关组件
from abc import ABC, abstractmethod

# 定义抽象基类
class Base(ABC):
    @abstractmethod
    def do_work(self):
        pass

# 子类实现抽象方法
class Impl(Base):
    def do_work(self):
        return "done"

9.2 最佳实践 #

9.3 适用与不适用 #

适合 不适合
插件/策略接口 简单父子继承
框架扩展点 不需要强制实现的方法
多实现可互换 只有一个实现的场景