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

时间:2016-12-04 21:22:21

标签: c# oop abstract design-principles liskov-substitution-principle

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.DoStuffabstract方法会发生什么:

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替换原则

2 个答案:

答案 0 :(得分:2)

这取决于定义合同的内容

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

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

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

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

public interface StuffContainer
{
    void Add(string text);

    // Removes a string that has previously been added.
    void Remove(string text);
}

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

答案 1 :(得分:1)

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

它只说明:

  

子类型要求:让phi(x)为a   关于T型物体x的可证明属性。然后   phi(y)应该是真的   S类型的对象y,其中S是T的子类型。

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

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

相关问题