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替换原则?
答案 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满足它。所以原则被违反了。
程序员必须坚持这一原则。一个属性也可以是“它做对了”,你可以通过一个方法错误实现的子类型来轻松破解。