抽象方法返回 self 类型

问题描述 投票:0回答:1

我的 mypy 遇到一些问题

所以我有一个抽象类和一个继承自它的类:

from __future__ import annotations

from abc import abstractmethod, ABC
from typing import Union


class Base(ABC):
    @abstractmethod
    def the_method(self, a_class: Union[Base, float, int]) -> None:
        ...

    @abstractmethod
    def other_method(self) -> None:
        ...


class MyClass(Base):
    def __init__(self, something: str = "Hello") -> None:
        self.something = something

    def the_method(self, a_class: Union[MyClass, float, int]) -> None:
        print(a_class)

    def other_method(self) -> None:
        print(self.something)

我知道里氏替换原则。然而

MyClass
Base
的一种类型,因为它继承了它。但
mypy
仍然引发错误:

main.py:21: error: Argument 1 of "the_method" is incompatible with supertype "Base"; supertype defines the argument type as "Base | float | int"  [override]
main.py:21: note: This violates the Liskov substitution principle
main.py:21: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides
Found 1 error in 1 file (checked 1 source file)

我做错了什么?

python inheritance mypy python-typing
1个回答
0
投票

Base.the_method
接受
Base
,所以子类也需要接受
Base
。如果我有
class Foo(Base)
,那应该被接受。目前,
MyClass.the_method
不接受。

您可以让

MyClass.the_method
接受
Base

class MyClass(Base):
    def __init__(self, something: str = "Hello") -> None:
        self.something = something

    def the_method(self, a_class: Union[Base, float, int]) -> None:
        print(a_class)

或更改

Base
以接受封闭类的实例

class Base(ABC):
    @abstractmethod
    def the_method(self, a_class: Union[Self, float, int]) -> None:
        ...

对于函数参数和返回类型,里氏替换的工作方向相反 - 子类可以作为参数,超类可以作为参数。

© www.soinside.com 2019 - 2024. All rights reserved.