One stumbles upon this phrase when reading about design patterns.
But I don't understand it, could someone explain this for me?
One stumbles upon this phrase when reading about design patterns.
But I don't understand it, could someone explain this for me?
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.
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
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.
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.
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.
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.
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.
alt text http://ruchitsurati.net/myfiles/interface.png
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.
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.
alt text http://demo.ruchitsurati.net/myfiles/interface1.png
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:
interfaces describe capabilities. when writing imperative code, talk about the capabilities you are using, rather than specific types or classes.