Я читал о Принципе замещения Лискова (LSP), и я немного смущен тем, как вы придерживаетесь его правильно. Особенно, когда используются интерфейсы и подклассы.C# 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. Добавление нулевой защиты к подклассу является нарушением LSP, правильно? Итак, как я мог бы создавать свои классы таким образом, чтобы они не нарушали LSP, но для одного из моих подклассов требуется дополнительный владелец учетной записи, а другой нет?
Подсоедините вопрос к тому факту, что могут быть тонны разных типов учетных записей, и их необходимо будет создать через фабрику или фабрику, которая возвращает строитель или что-то в этом роде.
И у меня тот же вопрос с интерфейсами. Если у меня есть интерфейс:
public interface IPrintsSomething
{
void PrintSomething(string text);
}
это не будет нарушением LSP добавить нулевой пункт охраны для текста любого класса, который реализует IPrintsSomething? Как вы защищаете свои инварианты? Правильно ли это слово? : p
Для примера AccountBase, как это работает с конструктором? Это нарушает LSP, чтобы иметь конструктор в подклассе, который требует SecondaryAccountHolder, когда конструктор базового класса этого не делает? –
Ваш конструктор защищен, поэтому это не имеет значения в отношении публичного контракта класса. Это также кажется излишним, поскольку подкласс может использовать соответствующие свойства. Если вы действительно хотите конструктор, он может принять как первичные, так и вторичные учетные записи, но держите его DRY - избегайте дублирования логики проверки и вместо этого назначайте свойства. –
Но если вы прямо назначаете свойства, то вы не гарантируете, что ваш объект находится в допустимом состоянии. Например, если я просто поместил свойство «RequiresSecondaryAccountHolder» в базовый класс, то это только гарантирует, что свойство не может быть установлено в null, что не гарантирует, что свойство действительно установлено. Таким образом, не требуется ли использование конструктора производного класса для сохранения объекта в допустимом состоянии? Нарушает ли LSP разные конструкторы на производных классах? –