views:

596

answers:

5

One stumbles upon this phrase when reading about design patterns.

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

+6  A: 

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
but how can a client interact with an interface and use its empty methods?
never_had_a_name
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
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
-1 This has nothing to do with Liskov.
Lucas
+26  A: 

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 Spakers 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

this. __curious_geek
wow...u just stole the point from Vincent:) thanks for the detailed explanation!
never_had_a_name
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
Factories are orthogonal to programming to interfaces, but I think this explanation makes it seem as though they're part of it.
Toon Van Acker
@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
Good example! Great answer!
Andersson Melo
@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
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
@ajsie: Updated the answer with modified example and class-diagram. Hope this helps.
this. __curious_geek
+2  A: 

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
+13  A: 

Think of an interface as a contract between and object an 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
Excellent explanation.
Neil Aitken
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
A: 

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

rektide