I have seen this mentioned a few times and I am not clear on what it means. When and why would you do this?
I know what interfaces do, but the fact I am not clear on this makes me think I am missing out on using them correctly.
Is it just so if you were to do:
IInterface classRef = new ObjectWhatever()
You could use any class that implements IInterface
? When would you need to do that? The only thing I can think of is if you have a method and you are unsure of what object will be passed except for it implementing IInterface
. I cannot think how often you would need to do that.
Also, how could you write a method that takes in an object that implements an interface? Is that possible?
It means just interact with an object or system's public interface. Don't worry or even anticipate how it does what it does internally. Don't worry about how it is implemented. In object-oriented code, it is why we have public vs.
Coding to interfaces is a technique by which developers can expose certain methods of an object to other objects in the system. The developers who receive implementations of these interfaces have the ability to code to the interface in place of coding to the object itself.
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.
Conclusion. As a developer you should be aware what patterns to use and why you use them. Your environment, team, or project may require using the coding against an interface pattern always, even if there is no benefit. Then, you may decide to follow the rule, if it does not have worse side effects.
There are some wonderful answers on here to this questions that get into all sorts of great detail about interfaces and loosely coupling code, inversion of control and so on. There are some fairly heady discussions, so I'd like to take the opportunity to break things down a bit for understanding why an interface is useful.
When I first started getting exposed to interfaces, I too was confused about their relevance. I didn't understand why you needed them. If we're using a language like Java or C#, we already have inheritance and I viewed interfaces as a weaker form of inheritance and thought, "why bother?" In a sense I was right, you can think of interfaces as sort of a weak form of inheritance, but beyond that I finally understood their use as a language construct by thinking of them as a means of classifying common traits or behaviors that were exhibited by potentially many non-related classes of objects.
For example -- say you have a SIM game and have the following classes:
class HouseFly inherits Insect { void FlyAroundYourHead(){} void LandOnThings(){} } class Telemarketer inherits Person { void CallDuringDinner(){} void ContinueTalkingWhenYouSayNo(){} }
Clearly, these two objects have nothing in common in terms of direct inheritance. But, you could say they are both annoying.
Let's say our game needs to have some sort of random thing that annoys the game player when they eat dinner. This could be a HouseFly
or a Telemarketer
or both -- but how do you allow for both with a single function? And how do you ask each different type of object to "do their annoying thing" in the same way?
The key to realize is that both a Telemarketer
and HouseFly
share a common loosely interpreted behavior even though they are nothing alike in terms of modeling them. So, let's make an interface that both can implement:
interface IPest { void BeAnnoying(); } class HouseFly inherits Insect implements IPest { void FlyAroundYourHead(){} void LandOnThings(){} void BeAnnoying() { FlyAroundYourHead(); LandOnThings(); } } class Telemarketer inherits Person implements IPest { void CallDuringDinner(){} void ContinueTalkingWhenYouSayNo(){} void BeAnnoying() { CallDuringDinner(); ContinueTalkingWhenYouSayNo(); } }
We now have two classes that can each be annoying in their own way. And they do not need to derive from the same base class and share common inherent characteristics -- they simply need to satisfy the contract of IPest
-- that contract is simple. You just have to BeAnnoying
. In this regard, we can model the following:
class DiningRoom { DiningRoom(Person[] diningPeople, IPest[] pests) { ... } void ServeDinner() { when diningPeople are eating, foreach pest in pests pest.BeAnnoying(); } }
Here we have a dining room that accepts a number of diners and a number of pests -- note the use of the interface. This means that in our little world, a member of the pests
array could actually be a Telemarketer
object or a HouseFly
object.
The ServeDinner
method is called when dinner is served and our people in the dining room are supposed to eat. In our little game, that's when our pests do their work -- each pest is instructed to be annoying by way of the IPest
interface. In this way, we can easily have both Telemarketers
and HouseFlys
be annoying in each of their own ways -- we care only that we have something in the DiningRoom
object that is a pest, we don't really care what it is and they could have nothing in common with other.
This very contrived pseudo-code example (that dragged on a lot longer than I anticipated) is simply meant to illustrate the kind of thing that finally turned the light on for me in terms of when we might use an interface. I apologize in advance for the silliness of the example, but hope that it helps in your understanding. And, to be sure, the other posted answers you've received here really cover the gamut of the use of interfaces today in design patterns and development methodologies.
The specific example I used to give to students is that they should write
List myList = new ArrayList(); // programming to the List interface
instead of
ArrayList myList = new ArrayList(); // this is bad
These look exactly the same in a short program, but if you go on to use myList
100 times in your program you can start to see a difference. The first declaration ensures that you only call methods on myList
that are defined by the List
interface (so no ArrayList
specific methods). If you've programmed to the interface this way, later on you can decide that you really need
List myList = new TreeList();
and you only have to change your code in that one spot. You already know that the rest of your code doesn't do anything that will be broken by changing the implementation because you programmed to the interface.
The benefits are even more obvious (I think) when you're talking about method parameters and return values. Take this for example:
public ArrayList doSomething(HashMap map);
That method declaration ties you to two concrete implementations (ArrayList
and HashMap
). As soon as that method is called from other code, any changes to those types probably mean you're going to have to change the calling code as well. It would be better to program to the interfaces.
public List doSomething(Map map);
Now it doesn't matter what kind of List
you return, or what kind of Map
is passed in as a parameter. Changes that you make inside the doSomething
method won't force you to change the calling code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With