tags:

views:

372

answers:

7

Given the following interfaces:

interface IFoo
{
    void Foo();
}

interface IBar : IFoo
{
    void Bar();
}

what is the best way to indicate that a given class implements IBar?

Approach A:

class Implementation : IBar { ... }

This seems simpler and cleaner but it does not indicate that Implementation implements IFoo.

Approach B:

class Implementation : IBar, IFoo { ... }

This seem the most informative but is the extra information really necessary?

+1  A: 

I'd go with A. You get to see which methods you need to implement in the class itself, and the navigation tools in the IDE will help you with the rest.

B would be impossible to maintain when doing any refactoring (eg, what happens if you replace IBar or split it into 2?)

simonjpascoe
+6  A: 

The extra information isn't necessary to the compiler, but it may be helpful to the reader of your code as the reader won't have to know that IBar extends IFoo. An example of this in the framework would be List<T> which implements <IList<T>, ICollection<T>, and IEnumerable<T>, even though IList<T>; extends both ICollection<T> and IEnumerable<T>.

EDIT: I think, for me at least, the primary reason that I would list both is that you ordinarily don't think of interfaces inheriting from one another. When you derive from a class, you expect that you are inheriting behavior that may itself be inherited. If you are interested, you follow the derivation up the class hierarchy. With an interface it's more unusual that the interface would be derived and thus you'd be less likely to look and more likely to miss the connection. Listing them both solves this problem without too much pain.

tvanfosson
@tvanfosson: isn't the reason for the framework doing this related to databinding?
Mitch Wheat
@Mitch - yes, it would also be necessary if you explicitly implemented any of the interfaces. Still IF I had an interface inheritance hierarchy, I'd likely list the interfaces. Why leave it up to the reader to guess which interfaces are implemented?
tvanfosson
A: 

I think Approach A is clear enough because (in VS.NET anyway) you can very quickly determine that IBar implements IFoo.

ankushnarula
+5  A: 

Personally I'd go with the former. With the latter, say you're in this situation where you have a bunch of derived classes:

class DerivedA : Implementation, IBar, IFoo { ... }
class DerivedB : Implementation, IBar, IFoo { ... }
class DerivedC : Implementation, IBar, IFoo { ... }
class DerivedD : Implementation, IBar, IFoo { ... }

And then your requirements for Implementation change so that it now needs to implement another interface such as IBaz (which it can do without having to affect any of the derived classes as long as it provides a non-abstract implementation) then you have two options:

  1. Leave all the derived class definitions without an explicit declaration of the new interface information, in which case the class definition is now incorrect according to the standard, and potentially misleading if people expect the standard to always be followed.

  2. Go and find all derived classes, and all their derived classes, and fix up the declarations on them. This takes time, is somewhat error prone and hard to do completely, and turns your single file change into a multi-file check-in.

Neither of these options is attractive, so I'd go with the option that doesn't put you in either situation. Just declare the most derived interface.

Greg Beech
I wouldn't worry about it when deriving from a class. In the case of interfaces, though, you don't normally expect inheritance and listing both would make it clear.
tvanfosson
A: 

Aside from readability and the differences in VB.NET (see Kathleen Dollard's comments), there is a situation with databinding that requires (B). The details have slipped my mind (I will edit unless someone beats me to it...).

I think this is the reason the .NET Framework collections explicitly implement their derived interfaces.

Mitch Wheat
+1  A: 

The fact that you've already implemented IFoo in IBar means that you don't even need to specify that your concrete implementation class implements IFoo; the CLR could infer that, and if you use Reflector on your assembly you'd see it specify that Implementation implements both IFoo and IBar even if you use Approach A.

So Approach A it is.

Jon Limjap
A: 

I would choose approach A simply because listing an interface in the list of derivations for a class definition implies that you are providing an implementation in that class. If you do not intend to provide an alternate implementation of IFoo, then I would not include it in the list, unless you need it as a simple "marker interface". Yet, even then, at runtime the "is" operator (returning true or false) or "as" keyword (returning an object or null) would tell you if an object could be cast to IFoo.

EnocNRoll