Reputation: 209
I'm trying to get into the habit of coding to an interface rather than an implementation and whilst in most cases I can see the reasoning there are a few where I struggle.
Take this really simple example:
public interface IAuditLog
{
void AddLog(string log);
}
public class AuditLog : IAuditLog
{
public void AddLog(string log)
{
//implementation
}
}
To call the audit log class:
public partial class AuditLogPage : System.Web.UI.Page
{
protected void btnAddLog_Click(object sender, EventArgs e)
{
IAuditLog objAuditLog = new AuditLog();
objAuditLog.AddLog("test log");
}
}
I still have to use AuditLog when instantiating, so what's the point? If the AddLog method signature changes i'm still going to have to go through all my pages that use it and amend the code. Am I missing the point?
Thanks for any help in advance, Wilky.
Upvotes: 1
Views: 1258
Reputation: 8502
This is actually useful when you create the AuditLog
instance from a method say like a Factory
method and you have more than one AuditLogXXX
classes derived from the IAuditLog
interface.
So, instead of using this code:
IAuditLog objAuditLog = new AuditLog();
You would actually use this code when you program to an interface:
IAuditLog objAuditLog = LogFactory.GetAuditLog(); //This call is programmed to an interface
where GetAuditLog()
is an interface typed method defined on the LogFactory
class as below:
class LogFactory
{
public IAuditLog GetAuditLog() // This method is programmed to an interface
{
//Some logic to make a choice to return appropriate AuditLogXXX instance from the factory
}
}
Upvotes: 1
Reputation: 13150
Let imagine that there there are two AuditLog classes
class AuditLogToDatabase : IAuditLog // writes to database
and another is
class AuditLogToFile : IAuditLog // writes to file
like
protected void btnAddLog_Click(object sender, EventArgs e)
{
IAuditLog objAuditLog = AuditLogFactory.GetAuditLog();
objAuditLog.AddLog("test log");
}
now you can inject any class based on some configuration at run time without changing the actual implementation
Upvotes: 4
Reputation: 16802
In the example if you switched out FileAuditLogger()
with DatabaseAuditLogger()
or EventLogAuditLogger()
you can switch implementations without having to rewrite your code.
Typically you'd use an IoC container (Autofac, StructureMap, Unity, etc.) to automatically wire up the object instantiation. So instead of calling new AuditLog()
you would call IoC.Container.Resolve<IAuditLog>()
Let me know if you'd like more information.
Upvotes: 5
Reputation: 354506
This doesn't necessarily mean that you have to actually use a C# interface
. An interface in OOP terms is the publicly visible façade of an API. It's a contract and externally visible results of operations should be specified. How exactly it works beneath the surface should be irrelevant so that you can swap out the implementation at any time.
Of course, in that regard an interface
is a method of being able to use different implementations, but so is an abstract base class or even a non-abstract class others can derive from.
But more to the exact point of your question: Of course, when instantiating a class its type must be known, but you don't necessarily have to create the class instance there. You could set an IAuditLog
from the outside or get it via a factory class, etc. where you wouldn't know, at that exact point in the code, what exact type you're getting (except that it's compatible with IAuditLog
).
Upvotes: 3