里斯科夫替代原则与内省或鸭类打字不相容吗?
我是否正确理解在对象可以自我检查的语言(如鸭式语言中常见的语言)中不能遵守《里斯科夫替代原理》? 例如,在Ruby中,如果一个类B从一个类继承A,然后为每个对象x的A,x.class是要回报A的,但如果x是一个对象B,x.class是不会返回A。 这是LSP的声明: 令q(x)是关于类型T的对象x的可证明性质。那么,对于类型S的对象y,q(y)应该是可证明的,其中S是T的子类型。 以Ruby为例, class T; end class S < T; end 如属性q(x) =所示,以这种形式违反LSPx.class.name == 'T' 加成。如果答案是“是”(与内省不兼容的LSP),那么我的另一个问题是:是否存在某种修改后的“弱”形式的LSP,它可能适用于动态语言,可能在某些附加条件下并且仅具有特殊类型的性质。 更新。作为参考,这是我在网络上发现的另一种LSP公式: 使用指针或对基类的引用的函数必须能够使用派生类的对象,而无需了解它。 还有一个: 如果S是声明的T的子类型,则将S类型的对象视为T类型的对象,如果将它们视为T类型的对象,则它们的行为也应与预期的T类型的对象相同。 最后一个注释为: 请注意,LSP全部关于对象的预期行为。只有清楚知道对象的预期行为后,才能遵循LSP。 这似乎比最初的要弱,并且可能可以观察到,但是我希望看到它正式化,尤其要解释谁决定预期的行为是什么。 那么,LSP是否不是编程语言中的一对类的属性,而是祖先类满足的一对类以及给定的一组属性?实际上,这是否意味着要构造一个尊重LSP的子类(后代类),必须知道祖先类的所有可能用法?根据LSP,祖先类应该可以用任何后代类替换,对吗? 更新。 我已经接受了答案,但是我想添加一个来自Ruby的更具体的例子来说明这个问题。在Ruby中,每个类都是模块,从某种意义上来说,Class类是类的后代Module。然而: class C; end C.is_a?(Module) # => true C.class # => Class Class.superclass # => Module module M; end M.class # => Module …