You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python方法重写:派生类使用更具体参数的合规实现方案

解决方案:用泛型绑定Document与对应Paragraph类型

问题出在你的基类Document的from_paragraphs方法参数是Sequence[Paragraph],但子类缩小了参数范围,只接受Sequence[LegalParagraph]/Sequence[AcademicParagraph],这违反了里氏替换原则——当子类被当作基类使用时,无法处理基类方法能接受的所有输入(比如给LegalDocument传入普通Paragraph序列)。

要解决这个问题,我们可以通过泛型让Document类与它能处理的Paragraph子类绑定,既满足类型约束,又通过类型检查:

from abc import ABC, abstractmethod
from typing import Sequence, TypeVar, Generic

# 定义一个受限于Paragraph子类的类型变量
P = TypeVar('P', bound='Paragraph')

class Document(ABC, Generic[P]):
    @classmethod
    @abstractmethod
    def from_paragraphs(cls, paragraphs: Sequence[P]) -> 'Document[P]':
        pass

class LegalDocument(Document['LegalParagraph']):
    @classmethod
    def from_paragraphs(cls, paragraphs: Sequence['LegalParagraph']) -> 'LegalDocument':
        # 具体实现逻辑
        return cls()

class AcademicDocument(Document['AcademicParagraph']):
    @classmethod
    def from_paragraphs(cls, paragraphs: Sequence['AcademicParagraph']) -> 'AcademicDocument':
        # 具体实现逻辑
        return cls()

class Paragraph:
    def __init__(self, text: str):
        self.text = text

class LegalParagraph(Paragraph):
    pass

class AcademicParagraph(Paragraph):
    pass

关键说明:

  • 用TypeVar定义了一个类型变量P,它只能是Paragraph或其子类,确保类型安全。
  • Document继承Generic[P]成为泛型类,每个子类继承时指定对应的Paragraph子类(比如Document['LegalParagraph'])。
  • 基类的from_paragraphs方法参数为Sequence[P],返回Document[P],子类实现时可以替换为具体的类型(比如Sequence[LegalParagraph]和LegalDocument)。这样类型检查器能正确识别每个子类的参数要求,同时不会违反里氏替换原则——因为此时LegalDocument是Document[LegalParagraph]的实例,而非Document[Paragraph],不会出现用基类类型引用子类后传入不兼容参数的情况。

内容的提问来源于stack exchange,提问作者malyvsen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 04:33:40