【发布时间】:2021-06-27 15:44:31
【问题描述】:
在某些情况下,结构子类型是否会导致无法使用 LSP?例如,假设我有一个带有标称类型的 Python* 设置,例如
class Foo(ABC):
def frobnicate(self) -> int:
""" frobnicate in a general fashion """
class SubFoo(Foo):
def frobnicate(self) -> int:
""" frobnicate in a particular fashion """
def bar(f: SubFoo) -> int:
return f.frobnicate()
我可以在bar 中确定我有一个SubFoo,并且由于 LSP,我知道调用它会“以一种特定的方式出现故障”。没关系。现在假设我改用结构子类型(注意Protocol)
class Foo(Protocol):
def frobnicate(self) -> int:
""" frobnicate in a general fashion """
class SubFoo(Foo, Protocol):
def frobnicate(self) -> int:
""" frobnicate in a particular fashion """
def bar(f: SubFoo) -> int:
return f.frobnicate()
我不能确定bar 我有一个SubFoo,因为Foo 也满足该协议,所以我可以,天堂禁止,“以一般方式进行frobnicate”。也就是说,LSP 不适用,因为子类型和超类型之间没有区别。
*我以 Python 为例,因为这就是我所知道的。这是一个与语言无关的问题,但我意识到这可能是由于 Python 的特殊性
【问题讨论】:
-
你能澄清一下你到底想知道什么吗?一方面,LSP 是关于能够用子类替换父类,或者换句话说,子类在结构上与父类相同。另一方面,协议仅与结构有关,因此
SubFoo.frobnicate的限制完全等同于Foo.frobnicate——两者都不是更通用的方式。 -
@MisterMiyagi 我想知道是否a)在鸭子打字的情况下不能假设LSP或b)我误解了一些东西
-
是的,我只是在往那个方向输入一个答案。 ;)
标签: python types duck-typing liskov-substitution-principle structural-typing