Я прочитал так много статей об этом, но у меня есть 2 вопроса.
Вопрос № 1 - Относительно инверсии зависимостей:
В нем говорится, что классы высокого уровня не должны зависеть от классов низкого уровня. Оба должны зависеть от абстракций. Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.
Например :
public class BirthdayCalculator
{
private readonly List<Birthday> _birthdays;
public BirthdayCalculator()
{
_birthdays = new List<Birthday>();// <----- here is a dependency
}
...
Исправление: поместите это в ctor.
public class BirthdayCalculator
{
private readonly IList<Birthday> _birthdays;
public BirthdayCalculator(IList<Birthday> birthdays)
{
_birthdays = birthdays;
}
Если он будет в ctor - мне придется отправлять его каждый раз, когда я использую класс. Так что мне придется оставить его при вызове класса
BirthdayCalculator
. это нормально делать это так?Я могу утверждать, что после исправления,
IList<Birthday> _birthdays
не должно быть там (Birthday
вIList
), но это должно быть какIList<IBirthday>
. Я прав ?
Вопрос № 2 - Относительно Замены Лискова:
производные классы должны быть заменяемыми на свои базовые классы
или точнее:
Пусть q (x) - свойство, доказуемое для объектов x типа T. Тогда q (y) должно быть истинным для объектов y типа S, где S - подтип T.
(уже прочитал это)
пример :
public abstract class Account
{
public abstract void Deposit(double amount);
}
У меня есть класс:
public class CheckingAccount : Account
{
public override void Deposit(double amount)
{ ...
_currentBalance += amount;
}
}
а банк хочет открыть ипотечный счет - итак:
public class MortgageAccount : Account
{
public override void Deposit(double amount)
{
_currentBalance -= amount; //<-----notice the minus
}
}
Проблема возникает, когда есть функция, которая принимает ипотеку как Account
и делает депозит.
public class Bank
{
public void ReceiveMoney(Account account, double amount)
{
double oldBalance = account.CurrentBalance;
account.Deposit(amount); //oopssss?????
}
}
так что здесь он нарушает LSP.
Но я не понимаю.
каждый переопределенный метод при переопределении будет выполнять другой код, поэтому он никогда не будет 100% заменяемым!
в определении НЕ говорилось о том, что «логика должна продолжаться, как в базовом классе (всегда вносить (добавлять) положительные числа)»
пример:
Что, если и CheckingAccount
класс, и MortgageAccount
класс вносили положительные числа, но MortgageAccount
также записывались в базу данных? он все еще ломает LSP? Какая граница для LSP обрывается / не тормозит?
определение должно определять, что это за граница. и это ничего не говорит об этом.
что мне не хватает?
Checking
иMortgage
являются отдельными ветвями в иерархии и не дают гарантии, что они реализуют то же самое дляDeposit
, они просто гарантируют, что реализуютDeposit
.Checking
иMortgage
не заменяют друг друга, но могут заменятьAccount
. 2) Фактический учет заMortgage
, вероятно, использует+=
, и еще один компонент просто преобразует отрицательный баланс в учетной записи в положительное число при отображении в пользовательском интерфейсе. - person David   schedule 17.12.2012