我试图通过反复阅读 wikipedia 来确定我对上述原则的理解。条目。
抛开仍然让我感到悲伤的协变和逆变的概念,维基百科还提到父类(super class)型的不变量必须保留在子类型和历史约束或历史规则中。基于这最后两个概念,我想出了这个小例子:
class Program
{
static void Main(string[] args)
{
var fooUser = new FooUser();
var fooBase = new FooBase("Serge");
var fooDerived = new FooDerived("Serge");
fooUser.Use(fooBase); //will print "Serge"
fooUser.Use(fooDerived); //will print "New User"
Console.ReadKey();
}
}
public class FooUser
{
public void Use(IFoo foo)
{
foo.DoSomething();
Console.WriteLine(foo.Name);
}
}
public interface IFoo
{
string Name { get; }
void DoSomething();
}
public class FooBase : IFoo
{
public string Name { get; protected set; }
public FooBase(string name)
{
Name = name;
}
public virtual void DoSomething()
{
}
}
public class FooDerived : FooBase
{
public FooDerived(string name) : base(name)
{
}
public override void DoSomething()
{
Name = "New Name";
base.DoSomething();
}
}
所以我的问题是:基于上面提到的两个概念,我这个例子是否违反了原则?如果不是,为什么?
非常感谢您。
最佳答案
要违反 LSP,您需要一个对类接口(interface)做出一些假设的客户端类。假设不能完全以正式的方式表达,有时它只是来自使用的上下文。
假设您有一个允许您添加元素的可枚举类。例如,客户端的假设可以是,如果它添加 N 个元素,则可以从集合中读取恰好 N 个元素。然后你从你的集合中派生一个集合,它在添加时删除重复的元素。现在客户的期望是错误的,因为即使添加了 N 个元素,有时也可以读取不到 N 个元素。
然后对我来说,违反 LSP 需要一个定义一些期望的上下文。由于您的代码中没有期望,因此没有违反 LSP。
这种对上下文的需求也意味着两个类可以违反一个客户端上下文的 LSP,而相同的类可能不会违反其他上下文中的 LSP。
关于c# - 了解 Liskov 替换原则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11472962/