我的 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)
我做错了什么?
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:
...
对于函数参数和返回类型,里氏替换的工作方向相反 - 子类可以作为参数,超类可以作为参数。