简体   繁体   English

结构(鸭子)类型与 LSP 兼容吗?

[英]Is structural (duck) typing compatible with LSP?

Does structural sub-typing make it impossible to use LSP in some cases?在某些情况下,结构子类型是否会导致无法使用 LSP? For example, say I have a Python* setup with nominal typing like例如,假设我有一个带有标称类型的 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()

I can be sure in bar that I have a SubFoo and because of LSP I know that calling it will "frobnicate in a particular fashion".我可以在bar中确定我有一个SubFoo ,并且由于 LSP,我知道调用它会“以特定的方式 frobnicate”。 That's all fine.没关系。 Now suppose I use structural sub-typing instead (note the Protocol )现在假设我改用结构子类型(注意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()

I can't be sure in bar I have a SubFoo because a Foo also satisfies that protocol, and so I may, heaven forbid, "frobnicate in a general fashion".我不能确定在bar我有一个SubFoo因为一个Foo也满足该协议,所以我可以,天堂禁止,“以一般方式进行 frobnicate”。 That is, LSP doesn't apply because there's no difference between subtypes and supertypes.也就是说,LSP 不适用,因为子类型和超类型之间没有区别。

*I've used Python as an example cos that's what I know. *我以 Python 为例,因为这就是我所知道的。 This is a language agnostic question, but I realise it may be due to Python specifics这是一个与语言无关的问题,但我意识到这可能是由于 Python 细节

LSP is a statement of consistency, not implementation. LSP 是一致性声明,而不是实现。

Subtype Requirement: Let ϕ(x) be a property provable about objects x of type T. Then ϕ(y) should be true for objects y of type S where S is a subtype of T.子类型要求:设 φ(x) 是关于 T 类型的对象 x 的可证明性质。那么 φ(y) 对于 S 类型的对象 y 应该为真,其中 S 是 T 的子类型。

Note how LSP is merely about types and subtypes in general – not nominal , structural or other subtypes in specific.请注意,LSP 仅涉及一般的类型和子类型——而不是具体的名义结构或其他子类型。

Paraphrased, one can say that "whatever a type guarantees, its subtype must guarantee as well".换句话说,可以说“无论一种类型保证什么,它的子类型也必须保证”。 Since structural types are only about structure – expressed as type guarantees – this is trivially satisfied.由于结构类型与结构有关 - 表示为类型保证 - 这很容易满足。


A structural type defines subtyping only in terms of structure.结构类型根据结构定义子类型。 For example, Foo defines the structural type:例如, Foo定义了结构类型:

{frobnicate: (Self) -> int}

Notably, this says that frobnicate exists, takes a Foo and returns an int .值得注意的是,这表示frobnicate存在,接受一个Foo并返回一个int It does not say anything about how that happens, or what relation there is between input and output.没有说明这是如何发生的,或者输入和 output 之间有什么关系。
Importantly, Foo does not say whether to frobnicate in a general or specific fashion.重要的是, Foo并没有说是用一般的方式还是特定的方式来frobnicate The implementation, docstring, or similar is not part of the type.实现、文档字符串或类似的不是类型的一部分。

Likewise, SubFoo defines the exact same structural type:同样, SubFoo定义了完全相同的结构类型:

{frobnicate: (Self) -> int}

As far as LSP is concerned, both substitutions SubFoo <: Foo and Foo <: SubFoo are valid: Foo and SubFoo differ only in ways not captured by structural typing, and thus not guaranteed by either type.就 LSP 而言, SubFoo <: FooFoo <: SubFoo两个替换都是有效的: FooSubFoo的区别仅在于结构类型捕获的方式,因此任何类型都不能保证。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM