里氏替换原理和原语句的方向性

发布于 2024-09-17 10:12:59 字数 508 浏览 7 评论 0原文

今晚我在 Ward 的 wiki 上看到了里氏替换原理的原始表述:

这里想要的是类似下面的替换属性:如果对于每个 S 类型的对象 o1 都有一个 T 类型的对象 o2,这样对于所有用 T 定义的程序 P,P 的行为在以下情况下保持不变: o1 替换 o2,则 S 是 T 的子类型。” - Barbara Liskov,数据抽象和层次结构,SIGPLAN 公告,23,5(1988 年 5 月)。

我在解析谓词逻辑方面一直很糟糕(我第一次在 Calc IV 中失败了)不过),所以虽然我有点理解上面的内容如何转化为:

使用基类指针或引用的函数必须能够在不知情的情况下使用派生类的对象。

我不明白的是为什么 Liskov 描述的属性暗示 S 是 T 的子类型,而不是相反。

也许我只是对 OOP 还不够了解,但是为什么 Liskov 的陈述只允许 S -> 的可能性? T,而不是 T -> S?

I came across the original statement of the Liskov Substitution Principle on Ward's wiki tonight:

What is wanted here is something like the following substitution property: If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T." - Barbara Liskov, Data Abstraction and Hierarchy, SIGPLAN Notices, 23,5 (May, 1988).

I've always been crap at parsing predicate logic (I failed Calc IV the first time though), so while I kind of understand how the above translates to:

Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.

what I don't understand is why the property Liskov describes implies that S is a subtype of T and not the other way around.

Maybe I just don't know enough yet about OOP, but why does Liskov's statement only allow for the possibility S -> T, and not T -> S?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

浮生未歇 2024-09-24 10:12:59

假设的程序集 P(用 T 表示)不是用 S 来定义的,因此它没有对 S 进行太多说明。另一方面,我们确实说 S 在该程序集中与 T 一样有效。程序 P,因此我们可以得出关于 S 及其与 T 的关系的结论。

思考这个问题的一种方法是 P 需要 T 的某些属性。S 恰好满足这些属性。也许你甚至可以说“S 中的每个 o1 也在 T 中”。这个结论用于定义单词亚型。

the hypothetical set of programs P (in terms of T) is not defined in terms of S, and therefore it doesn't say much about S. On the other hand, we do say that S works as well as T in that set of programs P, and so we can draw conclusions about S and its relationship to T.

One way to think about this is that P demands certain properties of T. S happens to satisfy those properties. Perhaps you could even say that 'every o1 in S is also in T'. This conclusion is used to define the word subtype.

樱花坊 2024-09-24 10:12:59

正如 sepp2k 所指出的,在另一篇文章中有多种观点解释了这一点。
这是我对此的两点看法。
我喜欢这样看

如果对于 TallPerson 类型的每个对象 o1 都有一个 Person 类型的对象 o2,这样对于以 Person 定义的所有程序 P,当 o1 替换 o2 时 P 的行为保持不变,然后 TallPerson是 Person 的子类型。 (用 TallPerson 替换 S,用 Person 替换 T)

我们通常认为派生某些基类的对象具有更多功能,因为它是扩展的。然而,随着功能的增加,我们对其进行了专门化,并缩小了它们的使用范围,从而成为其基类(更广泛的类型)的子类型。

As pointed by sepp2k there are multiple views explaining this in the other post.
Here are my two cents about it.
I like to look at it this way

If for each object o1 of type TallPerson there is an object o2 of type Person such that for all programs P defined in terms of Person, the behavior of P is unchanged when o1 is substituted for o2 then TallPerson is a subtype of Person. (replacing S with TallPerson and T with Person)

We typically have a perspective of objects deriving some base class have more functionality, since its extended. However with more functionality we are specializing it and reducing the scope in which they can be used thus becoming subtypes to its base class(broader type).

忆伤 2024-09-24 10:12:59

派生类继承其基类的公共接口,并期望使用继承的实现或提供行为类似的实现(例如,Count() 方法应返回元素的数量,无论如何这些元素被存储。)

基类不一定具有其派生类的任何(更不用说全部)的接口,因此期望没有意义对可替换指定派生类的基类的任意引用。即使看起来只需要基类的接口支持的接口子集,但情况可能并非如此(例如,可能会引用特定派生类中的隐藏方法)。

A derived class inherits its base class's public interface and is expected to either use the inherited implementation or to provide an implementation that behaves similarly (e.g., a Count() method should return the number of elements regardless of how those elements are stored.)

A base class wouldn't necessarily have the interface of any (let alone all) of its derived classes so it wouldn't make sense to expect an arbitrary reference to a base class to be substitutable for a specified derived class. Even if it appears that only the subset of the interface that supported by the base class's interface is required, that might not be the case (e.g., it could be that a shadowing method in the specific derived class is referred to).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文