Closed. This question needs to be more focused。它当前不接受答案。
想改善这个问题吗?更新问题,使其仅关注editing this post的一个问题。
1年前关闭。
Improve this question
您能用一个很好的C#示例以简单的方式解释Liskov替代原理(SOLID的“L”)吗?如果真的有可能。
和调用代码
如您所见,有两个鸭子的例子。一只有机鸭和一只电鸭。电动鸭子只有在打开的情况下才能游泳。这违反了LSP原理,因为必须将其打开才能游泳,因为
您当然可以通过执行以下操作来解决它
但这会破坏“打开/关闭”原理,必须在任何地方实现(因此仍然会生成不稳定的代码)。
正确的解决方案是使用
更新
有人添加了评论并将其删除。我想谈谈一个有效的观点:
在使用实际实现(
更新2
改写一些部分以使其更清晰。
想改善这个问题吗?更新问题,使其仅关注editing this post的一个问题。
1年前关闭。
Improve this question
您能用一个很好的C#示例以简单的方式解释Liskov替代原理(SOLID的“L”)吗?如果真的有可能。
最佳答案
(此答案已被改写为2013-05-13,请阅读评论底部的讨论)
LSP是关于遵循基类的契约(Contract)的。
例如,您不能在子类中引发新的异常,因为使用基类的异常不会发生这种情况。如果基类在缺少参数时抛出ArgumentNullException
,并且子类允许参数为null(同样违反LSP),则也是如此。
这是违反LSP的类结构的示例:
public interface IDuck
{
void Swim();
// contract says that IsSwimming should be true if Swim has been called.
bool IsSwimming { get; }
}
public class OrganicDuck : IDuck
{
public void Swim()
{
//do something to swim
}
bool IsSwimming { get { /* return if the duck is swimming */ } }
}
public class ElectricDuck : IDuck
{
bool _isSwimming;
public void Swim()
{
if (!IsTurnedOn)
return;
_isSwimming = true;
//swim logic
}
bool IsSwimming { get { return _isSwimming; } }
}
和调用代码
void MakeDuckSwim(IDuck duck)
{
duck.Swim();
}
如您所见,有两个鸭子的例子。一只有机鸭和一只电鸭。电动鸭子只有在打开的情况下才能游泳。这违反了LSP原理,因为必须将其打开才能游泳,因为
IsSwimming
(也是契约(Contract)的一部分)不会像在基类中那样设置。您当然可以通过执行以下操作来解决它
void MakeDuckSwim(IDuck duck)
{
if (duck is ElectricDuck)
((ElectricDuck)duck).TurnOn();
duck.Swim();
}
但这会破坏“打开/关闭”原理,必须在任何地方实现(因此仍然会生成不稳定的代码)。
正确的解决方案是使用
Swim
方法自动打开鸭子,并通过这种方式使电动鸭子的行为与IDuck
接口(interface)定义的完全相同更新
有人添加了评论并将其删除。我想谈谈一个有效的观点:
在使用实际实现(
Swim
)时,在ElectricDuck
方法内部打开鸭子的解决方案可能会有副作用。但这可以通过使用explicit interface implementation来解决。恕我直言,您更有可能通过在Swim
中不打开它来遇到问题,因为预期在使用IDuck
接口(interface)时它将游动更新2
改写一些部分以使其更清晰。
09-07 06:36