当前位置: 首页 > 知识库问答 >
问题:

如何看待带有子类型的多态性

微生善
2023-03-14

Liskov替代原则规定:

子类型中必须保留超类型的不变量。

我对这个原理和多态性的交叉点特别感兴趣。但在特定的子类型多态性中,事实上,参数多态性和Haskell类型类似乎就是这种情况。

所以,我知道函数是子类型,当它们的参数是逆变的,它们的返回类型是协变的。我们可以假设方法只是带有隐式“自我”参数的函数。然而,这似乎意味着如果子类重写父类的方法,它就不再是子类型,因为它的一个方法不再是子类型。

例如。获取以下伪代码:

class Parent:
    count : int
    increment : Parent -> ()
    {
        count += 1
    }

class Child inherits Parent:
    increment : Child -> ()
    {
        count += 2
    }

那么回到LSP:我们能不能说Parent.increment()的属性应该适用于Child.increment(),即使这两个属性不遵守严格的子类型关系?

更一般地说,我的问题是:子类型化规则如何与多态函数的更具体参数相结合,以及将这两个概念结合起来思考的正确方式是什么?

共有2个答案

段干楚青
2023-03-14

术语“子类型化”在技术上是一个句法问题。所以在语法上,Child

正如维基百科所指出的,利斯科夫原则是关于行为亚型的。它需要语法子类型,但也取决于您对类的不变量和前置/后置条件的定义。因为你没有定义任何,所以谈论违规行为是荒谬的。

如果将增量的后置条件定义为新计数=旧计数1,则存在冲突。

如果将增量的后置条件定义为新计数

一般来说,将后置条件定义为“完全是父代的后置条件”,使得通过定义不可能包含多态性。在多态性有意义的地方,后条件的定义应该放宽。

请注意,类不变量是关于可能的值-对象的快照-并且由于您可以根据父级的增量定义子级的增量,因此它不能违反任何不变量。

吕峰
2023-03-14

引用维基百科关于Liskov替代原理的文章

更正式地说,Liskov替代原则(LSP)是子类型关系的一个特殊定义,称为(强)行为子类型[…]

行为子类型是一个比类型理论中定义的函数的典型子类型更强的概念,它只依赖于参数类型的反方差和返回类型的协方差。行为分型一般来说是微不足道的不可判定的[...]

子类型必须满足许多行为条件:

  • 子类型中的前提条件不能加强

因此,LSP是一个更强的子类型定义,它依赖于类型理论之外的特性。

在您的示例中,这在您的不变量上上升和下降。

calling increment will increase count by **exactly 1**

显然,由于不变量被破坏,所以子对象不能用父对象来表示。这不能仅从语法推断。

LSP应该引导您分别定义父级和子级,让它们都继承自具有较弱post条件的Incrementable

 类似资料:
  • 问题内容: 我正在使用Jackson1.9.x。坚持以动物为例,这是我想做的: 假设我有一个Animal类: 我希望能够执行以下操作(将一些子类型映射到一个类,将更多子类型映射到另一个类): 我现在看到的是,杰克逊只会识别“狗到哺乳动物”和“渡渡鸟到鸟”的映射。这是因为StdSubtypeResolver._collectAndResolve()仅允许同一类注册一次(由于NamedType.equ

  • 问题内容: 如何在构造函数或类主体中定义类? 例如我想要的: 或具有类body属性的示例: 我的解决方案(但我希望看到更优雅的方式) 问题答案: 最神奇的方法不旨在与工作/ -在一般情况下,你应该只使用专用异步魔术方法里面- ,,,和。在其他魔术方法中使用它或者根本无法正常工作(除非您使用此处其他答案中描述的一些技巧),否则将迫使您始终在异步上下文中使用任何触发魔术方法调用的方法。 现有的库通常以

  • 我构建了以下内容: 上面的代码非常好,非常棒。然而,我仍然想要更多。我希望允许任何Iterable,而不是指定我的HList将包含列表。这样地: 第二个版本无法编译,并显示消息“无法找到参数映射器的隐式值:shapeless.ops.hlist.mapper[iterateOverHList.type,shapeless:[List[Int],shapeless:[List[String],sha

  • 我有一个抽象类的具体对象。 我在抽象类和子类上使用注释,但JSON输出看起来不正确,而且我一直在反序列化上遇到异常。 我还在学习杰克逊,不幸的是,很多关于这个主题的教程已经过时了。 以下是底部有我的对象映射器的类: 抽象类: 混凝土等级: Objectmapper块: 输出JSON: 例外: 其他答案(例如多态类型的Jackson反序列化)建议使用方法,但根据我阅读的教程,这应该没有必要。 不知道

  • 问题内容: 我的数据结构非常通用。几乎所有类型的数据都适合我的数据结构。 另一个文档可能是这样的: 该数据可以更改,并且字段可以具有任何类型和名称。如何动态创建模板映射,以便通过数据中“类型”的值来设置映射的“类型”?例如,值:34.50,类型:在同一时间浮动相同数据“值”:“哈利·波特”,类型:字符串 我已经知道ES中已经做到了这一点,但是我无法做出真正使用文档中指定的“ type”值来实际为该