我一直在阅读关于Liskov替换原则(LSP)的文章,我对如何正确地遵守它感到有点困惑。尤其是在使用接口和子类时。
例如,如果我有一个基类:
public abstract class AccountBase
{
private string primaryAccountHolder;
public string PrimaryAccountHolder
{
get { return this.primaryAccountHolder; }
set
{
if (value == null) throw ArgumentNullException("value");
this.primaryAccountHolder = value;
}
}
public string SecondaryAccountHolder { get; set; }
protected AccountBase(string primary)
{
if (primary == null) throw new ArgumentNullException("primary");
this.primaryAccountHolder = primary;
}
}现在假设我有两个从基类继承的帐户。其中一个需要SecondaryAccountHolder。向子类添加null防护是违反LSP的,对吗?那么,我如何设计我的类,使它们不违反LSP,但我的一个子类需要一个辅助帐户持有者,而另一个不需要?
将这个问题与一个事实相结合,即可能有大量不同类型的帐户,这些帐户需要通过工厂或返回构建器或其他东西的工厂生成。
对于接口,我也有同样的问题。如果我有一个接口:
public interface IPrintsSomething
{
void PrintSomething(string text);
}在任何实现IPrintsSomething的类上为文本添加空保护子句不是违反了LSP吗?你如何保护你的不变量?这是正确的词,对吗?
发布于 2016-12-22 05:07:52
那么,我如何设计我的类,使它们不违反
,但是我的一个子类需要一个辅助帐户持有者,而另一个不需要?
解决这个问题的方法是通过将这种可变性呈现给基类的契约。它可能看起来像这样(省略了不必要的实现细节):
public abstract class AccountBase
{
public string PrimaryAccountHolder
{
get { … }
set { … }
}
public string SecondaryAccountHolder
{
get { … }
set
{
…
if (RequiresSecondaryAccountHolder && value == null) throw …;
…
}
}
public abstract bool RequiresSecondaryAccountHolder { get; }
}那么您就没有违反LSP,因为AccountBase的用户可以决定他们是否必须提供SecondaryAcccountHolder的值。
和我对接口也有同样的问题。…在任何实现IPrintsSomething的类上为文本添加空保护子句不是违反了LSP吗?
使验证成为接口契约中显而易见的一部分。多么?文档中,实现者必须检查null的text的值。
https://stackoverflow.com/questions/41271696
复制相似问题