Liskov替换原则,前提条件和抽象方法

Liskov替换原则(LSP)说:

子类型不能强化前提条件。

在C#中,我可能违反以下原则:

public class A { public virtual void DoStuff(string text) { Contract.Requires(!string.IsNullOrEmpty(text)); } } public class B : A { public override void DoStuff(string text) { Contract.Requires(!string.IsNullOrEmpty(text) && text.Length > 10); } } 

但是,如果A.DoStuff是一个abstract方法会发生什么:

 public class A { public abstract void DoStuff(string text); } public class B : A { public override void DoStuff(string text) { Contract.Requires(!string.IsNullOrEmpty(text)); } } 

现在A.DoStuff没有合同 。 或者它的合同只是允许的一切

那么, B.DoStuff前提是否违反Liskov替换原则

这取决于合同的定义

LSP是一种理论构造,它不依赖于特定的语言或实现,例如C#的“代码合同”function。

合同可以通过以下方式定义:

  • 方法名称
  • 方法参数名称
  • 方法评论
  • 返回类型和方法参数类型
  • “显式”合同,如Contract.Requires

最后两个将由编译器validation。 但是,前三个也可以是合同的一部分! 请考虑以下示例:

 public interface StuffContainer { void Add(string text); // Removes a string that has previously been added. void Remove(string text); } 

Remove方法的名称和文档定义了一个明确的前提条件。 在实现中validation先前已添加要删除的字符串不会违反LSP。 validation字符串至少有5个字符会违反LSP。

是的,您可以非常轻松地破解原则,而不仅仅是在C#中。

它只说明:

子类型要求:让phi(x)成为关于类型T的对象x的可certificate的属性。对于S类型的对象y,phi(y)应该为真,其中S是T的子类型。

在您的示例中,类型B不满足提供使用短文本的方法DoStuff的属性,尽管其超类型A满足它。 所以原则被违反了。

这取决于程序员坚持原则。 一个属性也可以是“它做对了”,你可以通过一个方法错误实现的子类型来轻松破解。

我认为事实并非如此。 根据定义,抽象方法没有先决条件,因为没有实现。 如果实现接口破坏LSP,则与争论相同。

A.DoSomething()是无懈可击的,这是一个不真实的前提。 A.DoSomehing()未定义,因此它的签名不能超出其签名。