Wilky
Wilky

Reputation: 209

Program to an interface not an implementation confusion

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

Answers (4)

S2S2
S2S2

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

Asif Mushtaq
Asif Mushtaq

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

Kane
Kane

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

Joey
Joey

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

Related Questions