假设我们有以下示例(我花了一段时间才想到我的问题的一个最小示例,如果现实生活环境不是最好的,我很抱歉,但我认为我会比只使用和之类的名称Base
更好Child
)
from typing import *
from dataclasses import dataclass
@dataclass
class Product:
name: str
price: float
class Store:
def __init__(self, products: List[Product]):
self.products: List[Product] = products
def find_by_name(self, name) -> List[Product]:
return [product for product in self.products if product.name is name]
我已经为我的find_by_name
方法定义了返回类型,所以当我编码时,我可以知道返回类型是什么,并据此进行操作。
现在想象一下,我创建了我的 Product 和 Store 的子类(在这里它相当无用,但它确实很有必要,当然)。
class Fruit(Product):
color: str
class FruitStore(Store):
def __init__(self, fruits: List[Fruit]):
super().__init__(products=fruits)
def find_by_name_and_color(self, name, color) -> List[Fruit]:
return [fruit for fruit in self.find_by_name(name) if (fruit.name is name and fruit.color is color)]
# Expected List[Fruit], got List[Product] instead
正如注释掉的那样,PyCharm(和任何注释检查)将检测到此函数的返回类型与基于内容来自的函数的返回类型给出的内容不匹配。
出于可读性和更容易调试的目的,我尝试替换注释但没有运气:
def find_by_name(self, name) -> List[Fruit]: return super().find_by_name(name)
# Expected List[Fruit], got List[Product] instead
甚至替换整个函数都不够:
def find_by_name(self, name) -> List[Fruit]:
return [product for product in self.products if product.name is name]
# Expected List[Fruit], got List[Product] instead
我必须替换init中的变量定义:
def __init__(self, fruits: List[Fruit]):
self.products: List[Fruit] = fruits
反过来,这意味着替换整个类,并使继承无用。 如何只替换注释和返回类型而不必替换整个代码?
编辑:包括评论框中引入的术语(我不知道),我想我的问题会改写为:当使用具有较窄返回类型的子方法中的父类的广泛类型的方法时,如何允许逆变?
第二个想法,我认为将默认的广泛类型从父函数更改为标准的较窄类型比允许更广泛的返回类型更好。
丑图:
________________________________________________________________________
Input | Inner | Output
------------------------------------------------------------------------
|
(Parent.method -> broadType) |-> (Child.method2 -> narrowedType)
|
------------------------------------------------------------------------