例如,我们具有以下结构:

class Base
{
    [pure]
    public virtual bool IsValid(/*you can add some parameters here*/)
    {
       //body
    }
}

class Child : Base
{
    public override bool IsValid(/*you can add some parameters here*/)
    {
       //body
    }
}

您能否用不同的正文填充Base::IsValid()Child::IsValid(),但又不要与LSP冲突?假设这只是分析的方法,我们不能更改实例的状态。
我们能做到吗?
我对任何示例都感兴趣。
我尝试了解虚拟(实体) bool 方法在一般情况下是否为反模式

最佳答案

LSP的思想不禁止子类的多态性。相反,它强调允许更改的内容和不允许更改的内容。
通常,这意味着:

  • 任何覆盖函数都接受并返回相同类型的覆盖函数;其中可能包含抛出的异常(输入类型可能会扩展被覆盖的异常,而输出类型可能会缩小它们的范围-这仍将保持该限制)。
  • 子功能不能将子对象的“历史规则”-“基础”部分更改为使用基类功能永远无法达到的状态。因此,期望基础对象的函数将永远不会获得意外的结果。
  • 子代中不得更改Base的不变式。也就是说,有关基类行为的任何一般假设都必须由Child保留。

  • 前两个项目符号定义非常明确。 “不变式”更多是一个理性的问题。例如,如果实时环境中的某个类要求其所有功能在某个恒定时间内运行,则其子类型中的所有重写功能也必须遵守该要求。

    在您的情况下,IsValid()表示某些内容,并且“所有内容”必须保留在所有子类型下。例如,假设您的Base类定义了一种产品,并且IsValid()告知该产品是否有效出售。使每种产品有效的确切原因可能有所不同。例如,必须设置其价格才能对销售有效。但是, child 产品还必须经过电气测试,然后才能出售。

    在此示例中,我们保留所有要求:
  • 函数的输入和输出类型不变。
  • 不以Base类无法预期的方式更改Child对象的Base-part的状态。
  • 该类的不变量得以保留:没有价格的Child对象仍然无法出售;无效的含义仍然相同(不允许出售),只是以与子级匹配的方式进行计算。

  • 您可以得到更多的解释here

    ===

    编辑-根据注释进行一些其他解释

    多态的整体思想是,每个子类型都以不同的方式完成相同的功能。 LSP并不违反多态性,但描述了应注意的多态性。
    特别是,LSP要求在代码需要Child的情况下,可以使用任何子类型Base,并且对Base所做的任何假设都适用于他的任何Child。在上面的示例中,IsValis() 并不表示“有价格”。相反,这恰好意味着:产品有效吗?在某些情况下,有一个价格就足够了。换句话说,它还需要进行电力检查,而在另一些情况下,它可能还需要一些其他属性。如果Base类的设计者不要求通过设置价格来使产品变为有效,而是将IsValid()留作单独的测试,则不会发生违反LSP的情况。哪个例子会造成这种侵犯?一个示例,询问一个对象是否为IsValid(),然后调用基类的函数,该函数不应更改有效性,并且该函数将Child更改为不再有效。这违反了LSP的历史记录规则。这里其他人提供的已知示例是正方形,作为矩形的子级。但是,只要相同的函数调用序列不需要特定的行为(再次-没有定义设置价格使产品有效;在某些类型中恰好是这种方式)-LSP被保留。

    关于oop - 在不中断LSP的情况下覆盖虚拟 bool 纯方法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/50046333/

    10-09 09:49