Imagine that we're creating a new end-to-end POS system for a grocery store called BD Market. Let's assume for the time being that you know (or at least you think you know) everything you need to about the domain. So, like any eager programmer who doesn't want to waste his client's time and money you start creating classes - and here's what you have so far:
Notice any problems? If not, then it's a good thing you're reading this. Take another look at the code above and note the following:
- Both PerishableItem and NonPerishableItem have the data members Name, SKU, RetailPrice, and UnitPrice in common.
- Each implementation of the Scanner class's Scan and CancelScan methods does the exact same thing.
So, what can we do to avoid this mess now, and make it such that adding additional item types in the future won't break our Scanner class? We're going to create an interface called IProduct, that's what:
The IProduct interface defines signatures for the public properties that we want to expose in the classes that implement this interface. We can then refactor our Scanner class so that only one Scan() and one CancelScan() implementation is needed. See the updated code below:
The biggest (and most helpful) difference you can see is that now we only need one implementation of the Scan() and CancelScan() methods in our Scanner class. This has a future benefit as well, because as long as item types we create in the future implement the IProduct interface we do not have to concern ourselves with updating the Scanner class.
I hope that the brief example above has shown you how using interfaces can help you to write more robust code in your object-oriented projects. Please feel free to send any questions my way at brian (at) brian-driscoll (dot) com, or leave a comment below. You can also follow me on Twitter, I'm @driscollwebdev