views:

591

answers:

11

I have seen arguments for using explicit interfaces as a method of locking a classes usage to that interface. The argument seems to be that by forcing others to program to the interface you can ensure better decoupling of the classes and allow easier testing.

Example:

public interface ICut
{
    void Cut();
}
public class Knife : ICut
{
    void ICut.Cut()
    {
        //Cut Something
    }
}

And to use the Knife object:

ICut obj = new Knife();
obj.Cut();

Would you recommend this method of interface implementation? Why or why not?

EDIT: Also, given that I am using an explicit interface the following would NOT work.

Knife obj = new Knife();
obj.Cut();
A: 

If the client code doesn't care about anything other than the fact that it can use the object to Cut() things, then use ICut.

skaffman
+1  A: 

Well there is an organizational advantage. You can encapsulate your ICuttingSurface, ICut and related functionality into an Assembly that is self-contained and unit testable. Any implementations of the ICut interface are easily Mockable and can be made to be dependant upon only the ICut interface and not actual implementations which makes for a more modular and clean system.

Also this helps keep the inheritance more simplified and gives you more flexibility to use polymoprhism.

Steve g
A: 

Yes, but not necessarily for the given reasons.

An example:

On my current project, we are building a tool for data entry. We have certain functions that are used by all (or almost all) tabs, and we are coding a single page (the project is web-based) to contain all of the data entry controls.

This page has navigation on it, and buttons to interact with all the common actions.

By defining an interface (IDataEntry) that implements methods for each of the functions, and implementing that interface on each of the controls, we can have the aspx page fire public methods on the user controls which do the actual data entry.

By defining a strict set of interaction methods (such as your 'cut' method in the example) Interfaces allow you to take an object (be it a business object, a web control, or what have you) and work with it in a defined way.

For your example, you could call cut on any ICut object, be it a knife, a saw, a blowtorch, or mono filament wire.

For testing purposes, I think interfaces are also good. If you define tests based around the expected functionality of the interface, you can define objects as described and test them. This is a very high-level test, but it still ensures functionality. HOWEVER, this should not replace unit testing of the individual object methods...it does no good to know that 'obj.Cut' resulted in a cutting if it resulted in the wrong thing being cut, or in the wrong place.

Jeff
+2  A: 

Yes. And not just for testing. It makes sense to factor common behaviour into an interface (or abstract class); that way you can make use of polymorphism.

public class Sword: ICut
{    
  void ICut.Cut()   
  {        
     //Cut Something   
  }
}

Factory could return a type of sharp implement!:

ICut obj = SharpImplementFactory();

obj.Cut();
Mitch Wheat
+1  A: 

Using interfaces in this method does not, in and of itself, lead to decoupled code. If this is all you do, it just adds another layer of obfuscation and probably makes this more confusing later on.

However, if you combine interface based programming with Inversion of Control and Dependency Injection, then you are really getting somewhere. You can also make use of Mock Objects for Unit Testing with this type of setup if you are into Test Driven Development.

However, IOC, DI and TDD are all major topics in and of themselves, and entire books have been written on each of those subjects. Hopefully this will give you a jumping off point of things you can research.

Nick
+3  A: 

To quote GoF chapter 1:

  • "Program to an interface, not an implementation".
  • "Favor object composition over class inheritance".

As C# does not have multiple inheritance, object composition and programming to interfaces are the way to go.

ETA: And you should never use multiple inheritance anyway but that's another topic altogether.. :-)

ETA2: I'm not so sure about the explicit interface. That doesn't seem constructive. Why would I want to have a Knife that can only Cut() if instansiated as a ICut?

erlando
Both excellent design principles
Mitch Wheat
Regarding ETA2: Good Point... for the sake of argument... how about if I was implementing the Cut method of the IBlade interface and would like to use a knife... or sword?
chills42
+3  A: 

I've only used it in scenarios where I want to restrict access to certain methods.

public interface IWriter
{
    void Write(string message);
}

public interface IReader
{
    string Read();
}

public class MessageLog : IReader, IWriter
{
      public string Read()
      {
           // Implementation

          return "";
      }

      void IWriter.Write(string message)
      {
           // Implementation
      }
}

public class Foo
{
 readonly MessageLog _messageLog;
 IWriter _messageWriter;

 public Foo()
 {
   _messageLog = new MessageLog();
         _messageWriter = _messageLog;
 }

 public IReader Messages
 {
  get { return _messageLog; }
 }
}

Now Foo can write messages to it's message log using _messageWriter, but clients can only read. This is especially beneficial in a scenario where your classes are ComVisible. Your client can't cast to the Writer type and alter the information inside the message log.

ilitirit
+1  A: 

Allowing only callers expecting to explicit interface type ensures methods are only visible in the context they are needed in.

Consider a logical entity in a game and u decide that instead of a class responsibile for drawing/ticking the entities you want the code for tick/draw to be in the entity.

implement IDrawable.draw() and ITickable.tick() ensures an entity can only ever be drawn/ticked when the game expects it to. Otherwise these methods wont ever be visible.

Lesser bonus is when implementing multiple interfaces, explicit implementations let you work around cases where two interface method names collide.

Krypes
+2  A: 

This is a bad idea because their usage breaks polymorphism. The type of the reference used should NOT vary the behavior of the object. If you want to ensure loose coupling, make the classes internal and use a DI technology (such as Spring.Net).

dpurrington
+2  A: 

There are no doubt certain advantages to forcing the users of your code to cast your objects to the interface types you want them to be using.

But, on the whole, programming to an interface is a methodology or process issue. Programming to an interface is not going to be achieved merely by making your code annoying to the user.

Justice
+1  A: 

Another potential scenario for explicitly implementing an interface is when dealing with an existing class that already implements the functionality, but uses a different method name. For example, if your Knife class already had a method called Slice, you could implement the interface this way:

public class Knife : ICut
{
     public void Slice()
     {
          // slice something
     }

     void ICut.Cut()
     {
          Slice();
     }
}