I've read so many articles about this but still I have 2 questions.
Question #1 - Regarding Dependency Inversion :
It states that high-level classes should not depend on low-level classes. Both should depend on abstractions. Abstractions should not depend on details. Details should depend on abstractions.
for example :
public class BirthdayCalculator
{
private readonly List<Birthday> _birthdays;
public BirthdayCalculator()
{
_birthdays = new List<Birthday>();// <----- here is a dependency
}
...
The fix : put it in a ctor.
public class BirthdayCalculator
{
private readonly IList<Birthday> _birthdays;
public BirthdayCalculator(IList<Birthday> birthdays)
{
_birthdays = birthdays;
}
If it will be in ctor - I'll have to send it each and every time I use the class. So I will have to keep it when calling the
BirthdayCalculator
class. it it ok to do it like that ?I can argue that , after the fix , still -
IList<Birthday> _birthdays
should not by there ( theBirthday
inIList
) - but it should be asIList<IBirthday>
. Am I right ?
Question #2 - Regarding Liskov Substitution :
derived classes must be substitutable for their base classes
or more accurate :
Let q(x) be a property provable about objects x of type T. Then q(y) should be true for objects y of type S where S is a subtype of T.
(already read this )
example :
public abstract class Account
{
public abstract void Deposit(double amount);
}
I have a class :
public class CheckingAccount : Account
{
public override void Deposit(double amount)
{ ...
_currentBalance += amount;
}
}
and the bank wants to open a Mortgage account - so :
public class MortgageAccount : Account
{
public override void Deposit(double amount)
{
_currentBalance -= amount; //<-----notice the minus
}
}
The problem arises when there is a function which accepts mortage as Account
and do deposit.
public class Bank
{
public void ReceiveMoney(Account account, double amount)
{
double oldBalance = account.CurrentBalance;
account.Deposit(amount); //oopssss?????
}
}
so here , it violates the LSP.
But I don't understand.
every overridden method will do different code when overridden so it will never be 100% replaceable !
the definition did NOT talk about " logic should continue as in base class ( always deposit(add) positive numbers)"
example:
What if both CheckingAccount
class and MortgageAccount
class were depositing positive numbers but MortgageAccount
also log to db ? does it still breaks LSP ? What is the boundry for breaks/not-brakes LSP ?
the definition should define whatis that boundry. and it isn't saying anything about it.
what am i missing ?