(In the context of .NET for what its worth)
I tend to not use inheritance and rarely use interfaces. I came across someone who thinks interfaces are the best thing since spit. He uses them everywhere. I don't understand this and hence the questions that follow. I just want a check on my understanding of interfaces.
If you are using interfaces everywhere, I'm assuming you can predict the future, your app requirements are nailed down and nothing will ever change in your app. For me, during early development especially, interfaces become a drag. The app is very dynamic through its life. If you need to subtract or add members to the interface, lots of stuff will break. The guy above says he creates another interface to handle the new member(s). Nothing breaks.
Isn't that composition? Why not use composition without interfaces? More flexible.
How does he handle the case where a member must be subtracted from the interface? Basically he doesn't. Things just break and that is great because now you can see all of the affected areas and fix them. Instead of figuring out more elegantly where all of the related code paths are, we should just rip out parts of classes through brute force?
I think of a software application as a graph. A complete graph is the worst case, having n(n-1)/2. This means every class talks to every class. A confusing spider web. n-1 is the best, in which their is a strict hierarchy of communication. Adding another interface just to compensate for a new needed member adds a vertici to the graph, which means more edges and a stronger realization of the n(n-1)/2 equation. Composition without interfaces is more like mixins. Only select classes use particular methods. With an interface, all classes are forced to use members, even if they don't need them. The composition/mixin approach doesn't add new unneeded edges.
I'd refer to the .net design guidelines on this: http://msdn.microsoft.com/en-us/library/ms229013.aspx
There are a lot of reasons to use interfaces, but I also find that they're often overused for the wrong reasons. Interfaces provide much more flexibility when working with value types, and are incredibly useful when working with collections, etc, but when designing a class hierarchy for my own projects, I always try to think about simplicity first, and interfaces often lead to (unnecessarily) more complex situations.
My rule of thumb is to implement every BCL interface that makes sense, and only add my own interfaces into my designs when it actually provides something very valuable. Instead of having IWidgetManager, IWidgetManager2, etc... I'd much rather have abstract class WidgetManager and implement concrete methods as needed.
It is about dependencies. You want your code to depend on interface types instead of concrete types where appropriate. For example, you might have multiple concrete types that all perform similar behavior but implement it differently. Do you want your code base to have dependencies on those multiple concrete types, or one interface? How flexible do you think your code base will be when you need to make changes?
To your point about not wanting to use public members by using composition, I would say you're just encapsulating unnecessary dependencies. If you want to use composition, then you greatly reduce dependencies by composing interface types instead of concrete types.
For a better explanation, try looking at the literature on inversion of control.
It sounds like your friend was seriously mis-using interfaces.
I've also seen web apps with interfaces all over the place. Some people seem to have the idea that an interface is somehow better than just a regular method signature. Simple parameters already provide us with a contract--in most cases I believe this is enough, and makes for simpler code.
It seems to me that interfaces are most useful in cases like IDisposable or ICollection -- where they point to a certain set of functionality to expect from an object. In these cases they appear to be the right tool for the job.
Interfaces have many useful situations. When you need to add a specific behavior to a class that can be found across a wide variety of classes, that's a perfect time for an interface. A good example is the
IDisposable
interface - you have some resource that when you're done, needs to go away in a timely fashion. Is it a database connection? Is it some window handle? Doesn't matter.Another example would be when you really don't know how it should be implemented, such as an interface to an object that doesn't exist yet. Perhaps the object should be supplied by a client of your library, or must be implemented by a completely different module not under your control. You can basically design a contract for the methods available on the class.
That said, I only use them where it's needed. If I can do it with a regular class, or if it's something intrinsic to the particular object, I'll make it a class. There are some advantages to using Interfaces for every class as others have said, but that's so much extra overhead that I don't see a decent net gain on it. Most of the time, I've designed my class structures so that they're flat and wide, with as few dependencies as possible.
In summary: If you have common functionality required that's implemented dramatically differently, an Interface is just what you need.
One of the most important reasons for using an interface is the fact that they allow us to write unit tests for our classes and pass in our own dependencies. By putting the dependency behind an interface we open up "Seams" in our application code, where unit tests can easily be written. I don't see this test angle mentioned in many of the answers, but it is very important to understand that without interfaces, these dependencies (such as a web service, or a file system reference) can become very hard to test or at best are quite conditional. I have written a post here: http://jeffronay.com/why-use-an-interface/ that goes into much more detail with code examples showing a Service class without an interface, and then the same class re-written using an interface to demonstrate the testing flexibility when using interfaces.
We heavily use interfaces on custom UI elements, where each one is expecting a certain method to exist on another (and the interface forces that existence).