188

One stumbles upon this phrase when reading about design patterns.

But I don't understand it, could someone explain this for me?

andrew.fox
  • 7,435
  • 5
  • 52
  • 75
never_had_a_name
  • 90,630
  • 105
  • 267
  • 383
  • 6
    Possible duplicate of [What does it mean to "program to an interface"?](http://stackoverflow.com/questions/383947/what-does-it-mean-to-program-to-an-interface) – Rahul Shah Nov 26 '15 at 06:35

7 Answers7

188

Interfaces are just contracts or signatures and they don't know anything about implementations.

Coding against interface means, the client code always holds an Interface object which is supplied by a factory. Any instance returned by the factory would be of type Interface which any factory candidate class must have implemented. This way the client program is not worried about implementation and the interface signature determines what all operations can be done. This can be used to change the behavior of a program at run-time. It also helps you to write far better programs from the maintenance point of view.

Here's a basic example for you.

public enum Language
{
    English, German, Spanish
}

public class SpeakerFactory
{
    public static ISpeaker CreateSpeaker(Language language)
    {
        switch (language)
        {
            case Language.English:
                return new EnglishSpeaker();
            case Language.German:
                return new GermanSpeaker();
            case Language.Spanish:
                return new SpanishSpeaker();
            default:
                throw new ApplicationException("No speaker can speak such language");
        }
    }
}

[STAThread]
static void Main()
{
    //This is your client code.
    ISpeaker speaker = SpeakerFactory.CreateSpeaker(Language.English);
    speaker.Speak();
    Console.ReadLine();
}

public interface ISpeaker
{
    void Speak();
}

public class EnglishSpeaker : ISpeaker
{
    public EnglishSpeaker() { }

    #region ISpeaker Members

    public void Speak()
    {
        Console.WriteLine("I speak English.");
    }

    #endregion
}

public class GermanSpeaker : ISpeaker
{
    public GermanSpeaker() { }

    #region ISpeaker Members

    public void Speak()
    {
        Console.WriteLine("I speak German.");
    }

    #endregion
}

public class SpanishSpeaker : ISpeaker
{
    public SpanishSpeaker() { }

    #region ISpeaker Members

    public void Speak()
    {
        Console.WriteLine("I speak Spanish.");
    }

    #endregion
}

alt text

This is just a basic example and actual explanation of the principle is beyond the scope of this answer.

EDIT

I have updated the example above and added an abstract Speaker base class. In this update, I added a feature to all Speakers to "SayHello". All speaker speak "Hello World". So that's a common feature with similar function. Refer to the class diagram and you'll find that Speaker abstract class implement ISpeaker interface and marks the Speak() as abstract which means that the each Speaker implementation is responsible for implementing the Speak() method since it varies from Speaker to Speaker. But all speaker say "Hello" unanimously. So in the abstract Speaker class we define a method that says "Hello World" and each Speaker implementation will derive the SayHello() method.

Consider a case where SpanishSpeaker cannot Say Hello so in that case you can override the SayHello() method for Spanish Speaker and raise proper exception.

Please note that, we have not made any changes to Interface ISpeaker. And the client code and SpeakerFactory also remain unaffected unchanged. And this is what we achieve by Programming-to-Interface.

And we could achieve this behavior by simply adding a base abstract class Speaker and some minor modification in Each implementation thus leaving the original program unchanged. This is a desired feature of any application and it makes your application easily maintainable.

public enum Language
{
    English, German, Spanish
}

public class SpeakerFactory
{
    public static ISpeaker CreateSpeaker(Language language)
    {
        switch (language)
        {
            case Language.English:
                return new EnglishSpeaker();
            case Language.German:
                return new GermanSpeaker();
            case Language.Spanish:
                return new SpanishSpeaker();
            default:
                throw new ApplicationException("No speaker can speak such language");
        }
    }
}

class Program
{
    [STAThread]
    static void Main()
    {
        //This is your client code.
        ISpeaker speaker = SpeakerFactory.CreateSpeaker(Language.English);
        speaker.Speak();
        Console.ReadLine();
    }
}

public interface ISpeaker
{
    void Speak();
}

public abstract class Speaker : ISpeaker
{

    #region ISpeaker Members

    public abstract void Speak();

    public virtual void SayHello()
    {
        Console.WriteLine("Hello world.");
    }

    #endregion
}

public class EnglishSpeaker : Speaker
{
    public EnglishSpeaker() { }

    #region ISpeaker Members

    public override void Speak()
    {
        this.SayHello();
        Console.WriteLine("I speak English.");
    }

    #endregion
}

public class GermanSpeaker : Speaker
{
    public GermanSpeaker() { }

    #region ISpeaker Members

    public override void Speak()
    {
        Console.WriteLine("I speak German.");
        this.SayHello();
    }

    #endregion
}

public class SpanishSpeaker : Speaker
{
    public SpanishSpeaker() { }

    #region ISpeaker Members

    public override void Speak()
    {
        Console.WriteLine("I speak Spanish.");
    }

    public override void SayHello()
    {
        throw new ApplicationException("I cannot say Hello World.");
    }

    #endregion
}

alt text

Hesham Massoud
  • 1,550
  • 1
  • 11
  • 17
this. __curious_geek
  • 42,787
  • 22
  • 113
  • 137
  • 23
    Programming to the interface is not **only** about the type of the reference variable. It also means that you don't use any implicit assumptions about your implementation. For example if you use a `List` as the type, your still could still be assuming that random access is fast by repeatedly calling `get(i)`. – Joachim Sauer Apr 23 '10 at 11:36
  • 23
    Factories are orthogonal to programming to interfaces, but I think this explanation makes it seem as though they're part of it. – T . Apr 23 '10 at 13:58
  • @Toon: agree with you. I wanted to provide a very basic and simple example for programming-to-interface. I didn't want to confuse the questioner by implementing IFlyable interface on few birds' and animals' classes. – this. __curious_geek Apr 23 '10 at 14:09
  • @this. if i instead use an abstract class or a facade pattern, will it still be called "program to an interface"? or do i explicitly have to use an interface and implement it on a class? – never_had_a_name Apr 23 '10 at 19:57
  • No. using abstract class would be a different scenario as compared to "program-to-interface". In this case you'd have your abstract class implement an interface and let other classes be inherited from the abstract class which will also make them inherit the Interface as well. Will update my examples for your reference soon. – this. __curious_geek Apr 23 '10 at 20:44
  • @ajsie: Updated the answer with modified example and class-diagram. Hope this helps. – this. __curious_geek Apr 24 '10 at 15:06
  • One of the image url is broken :( – appbootup Mar 12 '13 at 03:18
  • 1
    What uml tool were you using to create the images? – Adam Arold Jun 25 '13 at 10:59
  • "... the client code always holds an Interface object which is supplied by a factory". No, this is incorrect. It's not what the principle is about. If you write `List aList = new ArrayList()`, you are coding to the `List` interface, not to the `ArrayList` implementation (using Java here). Even more, if you use a class with no separate interface, such as `StringBuilder bldr = new StringBuilder()` (which implements the `CharSequence` interface, but we can ignore that here) you are *still* coding to an interface, not an implementation (the *implicit* public interface of class `StringBuilder`). – Rogério Sep 19 '14 at 19:27
  • ok, why having an abstract class and an interface. you could've had just an abstract class and have subclasses extend that class. The first implementation makes more sense to me an interface and the 3 sub-classes, which if I'm not mistaken is Factory-Pattern. – miatech Feb 18 '20 at 15:01
38

Think of an interface as a contract between an object and its clients. That is the interface specifies the things that an object can do, and the signatures for accessing those things.

Implementations are the actual behaviours. Say for example you have a method sort(). You can implement QuickSort or MergeSort. That should not matter to the client code calling sort as long as the interface does not change.

Libraries like the Java API and the .NET Framework make heavy use of interfaces because millions of programmers use the objects provided. The creators of these libraries have to be very careful that they do not change the interface to the classes in these libraries because it will affect all programmers using the library. On the other hand they can change the implementation as much as they like.

If, as a programmer, you code against the implementation then as soon as it changes your code stops working. So think of the benefits of the interface this way:

  1. it hides the things you do not need to know making the object simpler to use.
  2. it provides the contract of how the object will behave so you can depend on that
Vincent Ramdhanie
  • 102,349
  • 23
  • 137
  • 192
  • It does mean you need to be aware of what you are contracting the object to do: in the example provided you are only contracting for a sort, not necessarily a stable sort. – penguat Apr 23 '10 at 13:23
  • So similar to how library documentation doesn't mention implementation, they are just descriptions of included class interfaces. – Joe Iddon Oct 30 '18 at 08:16
28

It means that you should try to write your code so it uses an abstraction (abstract class or interface) instead of the implementation directly.

Normally the implementation is injected into your code through the constructor or a method call. So, your code knows about the interface or abstract class and can call anything that is defined on this contract. As an actual object (implementation of the interface/abstract class) is used, the calls are operating on the object.

This is a subset of the Liskov Substitution Principle (LSP), the L of the SOLID principles.

An example in .NET would be to code with IList instead of List or Dictionary, so you could use any class that implements IList interchangeably in your code:

// myList can be _any_ object that implements IList
public int GetListCount(IList myList)
{
    // Do anything that IList supports
    return myList.Count();
}

Another example from the Base Class Library (BCL) is the ProviderBase abstract class - this provides some infrastructure, and as importantly means all provider implementations can be used interchangeably if you code against it.

Oded
  • 489,969
  • 99
  • 883
  • 1,009
  • but how can a client interact with an interface and use its empty methods? – never_had_a_name Apr 23 '10 at 10:49
  • 2
    Client does not interact with the interface, but through the interface:) Objects interact with other objects through methods (messages) and an interface is a sort of a language - when you know that certain object (person) implements (speaks) english (IList), you can use it withouth any need to know more about that object (that he is also an Italian), because it is no needed in that context (if you want to ask for help you do not need to know he speaks also Italian if you understand English). – Gabriel Ščerbák Apr 23 '10 at 10:59
  • 1
    BTW. IMHO Liskov substitution principle is about semantic of inheritance and has nothing to do with interfaces, which can be found also in languages without inheritance (Go from Google). – Gabriel Ščerbák Apr 23 '10 at 11:01
  • @GabrielŠčerbák I agree. Interface-Segregation-Prinziple (ISP) should be mentioned over LSP. ISP is more correct because a interface can be smaller than the implementation, a interface therefore is more abstract. – Grim Nov 21 '22 at 10:05
9

If you were to write a Car Class in Combustion-Car era, then there is a great chance you would implement oilChange() as a part of this Class. But, when electric cars are introduced, you would be in trouble as there is no oil-change involved for these cars, and no implemention.

The solution to the problem is to have a performMaintenance() Interface in Car class and hide details inside appropriate implementation. Each Car type would provide its own implementation for performMaintenance(). As a owner of a Car all you have to deal with is performMaintenance() and not worry about adapting when there is a CHANGE.

class MaintenanceSpecialist {
    public:
        virtual int performMaintenance() = 0;
};

class CombustionEnginedMaintenance : public MaintenanceSpecialist {
    int performMaintenance() { 
        printf("combustionEnginedMaintenance: We specialize in maintenance of Combustion engines \n");
        return 0;
    }
};

class ElectricMaintenance : public MaintenanceSpecialist {
    int performMaintenance() {
        printf("electricMaintenance: We specialize in maintenance of Electric Cars \n");
        return 0;
    }
};

class Car {
    public:
        MaintenanceSpecialist *mSpecialist;
        virtual int maintenance() {
            printf("Just wash the car \n");
            return 0;
        };
};

class GasolineCar : public Car {
    public: 
        GasolineCar() {
        mSpecialist = new CombustionEnginedMaintenance();
        }
        int maintenance() {
        mSpecialist->performMaintenance();
        return 0;
        }
};

class ElectricCar : public Car {
    public: 
        ElectricCar() {
             mSpecialist = new ElectricMaintenance();
        }

        int maintenance(){
            mSpecialist->performMaintenance();
            return 0;
        }
};

int _tmain(int argc, _TCHAR* argv[]) {

    Car *myCar; 

    myCar = new GasolineCar();
    myCar->maintenance(); /* I dont know what is involved in maintenance. But, I do know the maintenance has to be performed */


    myCar = new ElectricCar(); 
    myCar->maintenance(); 

    return 0;
}

Additional explanation: You are a car owner who owns multiple cars. You carve out the service that you want to outsource. In our case we want to outsource the maintenance work of all cars.

  1. You identify the contract(Interface) that holds good for all your cars and service providers.
  2. Service providers come out with a mechanism to provide the service.
  3. You don't want to worry about associating the car type with the service provider. You just specify when you want to schedule maintenance and invoke it. Appropriate service company should jump in and perform the maintenance work.

    Alternate approach.

  4. You identify the work(can be a new interface Interface) that holds good for all your cars.
  5. You come out with a mechanism to provide the service. Basically you are going to provide the implementation.
  6. You invoke the work and do it yourself. Here you are going to do the job of appropriate maintenance work.

    What is the downside of the 2nd approach? You may not be the expert at finding the best way to do the maintenance. Your job is to drive the car and enjoy it. Not to be in the business of maintaining it.

    What it the downside of the first approach? There is the overhead of finding a company etc. Unless you are a rental car company, it may not be worth the effort.

Raghav Navada
  • 307
  • 2
  • 7
6

As others have said, it means that your calling code should only know about an abstract parent, NOT the actual implementing class that will do the work.

What helps to understand this is the WHY you should always program to an interface. There's many reasons, but two of the easiest to explain are

1) Testing.

Let's say I have my entire database code in one class. If my program knows about the concrete class, I can only test my code by really running it against that class. I'm using -> to mean "talks to".

WorkerClass -> DALClass However, let's add an interface to the mix.

WorkerClass -> IDAL -> DALClass.

So the DALClass implements the IDAL interface, and worker class ONLY calls through this.

Now if we want to write tests for the code, we could instead make a simple class that just acts like a database.

WorkerClass -> IDAL -> IFakeDAL.

2) Reuse

Following the example above, let's say we want to move from SQL Server (which our concrete DALClass uses) to MonogoDB. This would take major work, but NOT if we've programmed to an interface. In that case we just write the new DB class, and change (via the factory)

WorkerClass -> IDAL -> DALClass

to

WorkerClass -> IDAL -> MongoDBClass

Mathieson
  • 1,698
  • 2
  • 17
  • 19
6

This statement is about coupling. One potential reason for using object oriented programming is reuse. So for example you can split your algorithm among two collaborating objects A and B. This might be useful for later creation of another algorithm, which might reuse one or another of the two objects. However, when those objects communicate (send messages - call methods), they create dependencies among each other. But if you want to use one without the other, you need to specify what should do some other object C do for object A if we replace B. Those descriptions are called interfaces. This allows object A to communicate without change with different object relying on the interface. The statement you mentioned says that if you plan to reuse some part of an algorithm (or more generally a program), you should create interfaces and rely on them, so you might change the concrete implementation any time without changing other objects if you use the declared interface.

Gabriel Ščerbák
  • 18,240
  • 8
  • 37
  • 52
3

interfaces describe capabilities. when writing imperative code, talk about the capabilities you are using, rather than specific types or classes.

rektide
  • 1,492
  • 13
  • 21