Reputation: 71
interface IBankAccount
{
void PayIn(decimal amount);
bool Withdraw(decimal amount);
decimal Balance { get; }
}
interface ITransferBankAccount : IBankAccount
{
bool TranferTo(IBankAccount destination, decimal amount);
}
class CurrentAccount : ITransferBankAccount
{
public bool TranferTo(IBankAccount destination, decimal amount)
{
bool result;
result = Withdraw(amount);
if (result)
{
destination.PayIn(amount);
}
return result;
}
public decimal Balance
{
get
{
throw new NotImplementedException();
}
}
public void PayIn(decimal amount)
{
throw new NotImplementedException();
}
public bool Withdraw(decimal amount)
{
throw new NotImplementedException();
}
Demo Code showing This technique Thanks in Advance
Upvotes: 3
Views: 13346
Reputation: 53958
You achieve to implement a principle that says
Program to an interface, not an implementation.
This has been introduced by GoF in their seminal book called Design Patterns. The benefits of adhering to such a practice are the following:
Based on the example you have posted we have two interfaces:
interface IBankAccount
{
void PayIn(decimal amount);
bool Withdraw(decimal amount);
decimal Balance { get; }
}
interface ITransferBankAccount : IBankAccount
{
bool TranferTo(IBankAccount destination, decimal amount);
}
The interface IBankAccount
is composed from two methods and one property that each bank account should have (at least in the perspective of the author of this interface and the problem she/he tried to solve).
Specifically, we should be able to deposit money (PayIn
) and withdraw money (Withdraw
) from a bank account and last but not least to read the account's balance Balance
.
Regarding the second interface, ITransferBankAccount
this exhibits a behavior that only some accounts may have. This behavior is to transfer money. We could assume that there are two kinds of bank accounts those from which you can transfer money from one bank account to another and those that you can't, you can only deposit/withdraw from that specific bank account. It's just an assumption tied to this specific problem that Author of theses interfaces she/he tried to solve,
Even before we proceed to the CurrentAccount
the benefits of interfaces are evident in the second interface !
We define a behavior, those of transferring money and we don't require the TranferTo
method has as it's first parameter a custom type like CurrentAccount
or another type. We just require that the first parameter of this method should implement the interface IBankAccount
. Just this ! This is enough for us to transfer some money, since we can deposit money to an account by using the PayIn
method.
Why the latter is important?
For instance let that we have 3 bank accounts A, B, C. Furthermore, let's assume that the account B and account C are different in terms of business. For instance whenever account B receives an amount of money we should do some extra actions if we compare it with account C. Definetely that means that in order to model this we should have two different classes. BankAccount_B
and BankAccount_C
. In addition to this let's suppose that whenever we Withdraw money from A to any other account we have to get a specific fee and apply some extra logic. That definitely means that bank account A should be modelled using another class. Let's call it BankAccount_A
.
If we suppose that all these classes BankAccount_A
, BankAccount_B
and BankAccount_C
implement the interface IBankAccount
and the class BankAccount_A
implements the interface ITransferBankAccount
, then your can write code like this:
var bankAccountA = new BankAccount_A();
// Deposit $100 in Bank Account A
bankAccountA.PayIn(100);
var bankAccountB = new BankAccount_B();
var bankAccountC = new BankAccount_C();
// Transfer $ 60 to bank account B from A
bankAccountA.TransferTo(bankAccountB, 60);
// Transfer $ 40 to bank account B from A
bankAccountA.TransferTo(bankAccountC, 40);
Suppose that now you didn't have followed this principle and you wanted to implement the above functionality. In this case you should have defined two methods in class BankAccount_A
. One for transferring money to bank accounts that are created using the BankAccount_B
and one another for transferring money to bank accounts that are created using the BankAccount_C
. And what about if you had another requirement for another account D in the future ? You should define another method etc...And this time you should violate one of the principles of SOLID, the Open/Closed principle, software entities … should be open for extension, but closed for modification. Had we used the interface we had been closed for modification :).
Upvotes: 7
Reputation: 3687
Basically, you can pass in any class that conforms to that interface.
Upvotes: 4
Reputation: 82524
Well, I was going to comment on Christos's answer but it's getting too long so I'll post this as a supplement answer:
To answer the question one must first understand what an interface is. Most developers will tell you that an interface is a contract for a class. If you ask them what that actually means, I'm not sure most of them will be able to explain it to a person that doesn't already have at least a basic understanding of object oriented programming.
So, what is a better explanation of an interface?
IMHO, an interface is best explained literaly - It's a list of guaranteed ways one can interact with an instance of a class that's implementing this interface. It's not a complete list - since nothing is stopping that class to add functionality such as method and properties beyond that interface, but - and that's the important part - it's guaranteed that each method, property, event or indexer on the interface is actually included in the class.
Why is that so important and how does it makes your life as a programmer better?
It's important since it means you can use interfaces instead of concrete implementations.
Why would you want to do that?
A
as a parameter, and later on decided to add class B
that will also use this method, you would have to write another method accepting B
as a parameter. By using an interface as an argument for your method, all you need to do is have both A
and B
implement the same interface (and that could be a completely different implementation), and then simply pass A
or B
, since the both Are, by polymorphism, that interface.Upvotes: 6