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,这与争论是一样的。
说A. Do某物()
是无契约的是一个不真实的前提。A. Do某物()
是未定义的,因此它不能有超过其签名的契约。
是的,你可以很容易地打破这个原则,不仅仅是在C。
它只指出:
子类型要求:设phi(x)是关于T类型的对象x的可证明属性。那么,对于S类型的对象y,phi(y)应该为真,其中S是T的子类型。
在您的示例中,类型B不满足提供处理短文本的方法DoStuff
的属性,尽管它的超类型a满足该属性。所以这个原则被违反了。
程序员应该坚持这个原则。属性也可以是“它做正确的事情”,您可以很容易地通过使用带有错误方法实现的子类型来打破它。
这取决于合同的定义。
LSP是一种理论构造,它不依赖于特定的语言或实现,例如C#的“代码契约”特性。
合同的定义如下:
合同。需要
最后两个将由编译器验证。然而,前三个也可以是合同的一部分!考虑以下示例:
public interface StuffContainer
{
void Add(string text);
// Removes a string that has previously been added.
void Remove(string text);
}
Remove
方法的名称和文档定义了一个明确的先决条件。在实现中验证要删除的字符串之前已添加不会违反LSP。验证字符串是否至少包含5个字符将违反LSP。
我在派生类中重写了带有附加先决条件的虚拟函数。这是快照- 如果我理解正确的话,这里的代码通过附加一个先决条件打破了Liskov替换-IsImmediateProcess和其他日期检查。对吗?或者一个被重写的函数调用一个基函数,然后向它添加自己的行为,这样可以吗? 我不能将重写方法中由初始过程类型引入的条件移动到基本类型,因为它是特定于初始过程的。 在这种情况下,如果派生类重写行为并希望在不违反Li
存在无法写入或查找的流派生类这一事实是否违反了Liskov替换原则? 例如,无法查找NetworkStream,如果调用方法,它将抛出。 还是因为存在标志就可以了? 考虑到众所周知的继承自的例子...将标志和添加到是否可以解决问题? 这难道不是打开了通过添加旗帜来解决问题的大门吗?
每个类都直接或间接地继承自类。 类有一个重要的方法,最常被重写:。 问题是:对于类,重写此方法是否会违反Liskov替换原则? 我举个例子。 显然,如果我用替换,系统的行为就会改变。
我试图理解Liskov替换原理,我有以下代码: 我不确定这是否违反了它。原理是,如果你有一个类S的对象,那么你可以用另一个类T的对象来代替它,其中S是T的一个子类。但是,如果我写了 这当然会产生编译错误,因为Vehicle类没有openDoor()方法。但这意味着我不能用它们的父类Vehicle替换VehicleWithDoors对象,这似乎违反了原则。那么这个代码是否违反了它?我需要一个好的解释
我试图通过反复阅读维基百科条目来确定我对上述原则的理解。 撇开仍然让我悲伤的协变和逆变的概念不谈,wikipedia还提到超类型的不变量必须保留在子类型和历史约束或历史规则中。基于最后两个概念,我提出了一个小例子: 所以我的问题是:基于上述两个概念,我用这个例子是否违反了原则?若否,原因为何? 事先非常感谢。