views:

269

answers:

5

I've just used it for the first time - consider:

IGameObject
    void Update()

IDrawableGameObject : IGameObject
    void Draw()

I had a level class which used DrawableGameObjects - I switched this to be IDrawableGameObject's instead to reduce coupling and aid in TDD.

However I of course lose the ability to call Update(..) without casting - to get around this I used inheritance. I've never used interface based inheritance before - nor have I really found the need except in this case.

I didn't really want to cast each time in my update method as it is called up to 60 times a second, on the other hand a foreach(..) could have worked that used IGameObject's.

Any advice?

Edit

I should add - my fake's I created afterwards for unit testing then implement IDrawableGameObject - these classes now have many methods instead of just a handful for each interface. I know interfaces must be only a handful of members large, but does inheritance break this rule?

Thanks

+2  A: 

Interface based inheritance is really no different than normal inheritance in terms of "should you do it". It still expresses an "is a" relationship between two types. So in this case if IDrawableGameObject is indeed an IGameObject as it appears to be, the inheritance makes sense.

JaredPar
I disagree. Interface inheritance need not describe an "is a" relationship between two types. I prefer to think of interfaces as representing contracts. Interface "inheritance" of IX : IY means "In order to fulfill the terms of contract X, you must also fulfill the terms of contract Y. For example, is there an "is a" relationship between enumerable and disposable? A sequence is not "a kind of disposable" in the way that a giraffe is a kind of mammal. Rather, to fulfill the requirements of the "can be enumerated" contract, you must also fulfill the requirements of the disposal contract.
Eric Lippert
I prefer to think of interfaces along the lines of "if it walks like a duck, quacks like a duck, then it is in fact a duck". Given a properly implemented interface, a consumer should not be able to differentiate an actual implementation from an imposter (arrays or List<T> enumerators faking IDisposable). (cont)
JaredPar
From the view point of those interfaces I would say a sequence is a disposable. I definitely agree there is no "is a" relationship when the concrete implementations are considered. But from the standpoint of designing the interfaces I think a "is a" or perhaps more appropriately an "acts like a" can be used to describe the relationship
JaredPar
A: 

The thing to watch out for with interface inheritance applied in this way is that additions to the root interface can create large amounts of work to make the implementations of the interface compliant with the new change (in a large project). It can also make it more difficult to make a good judgment as to which interface a method belongs in if you have multiple layers of interface inheritance.

Paul Morie
+3  A: 

I know interfaces must be only a handful of members large

They need to contain exactly as many members as are necessary to express the concept - no more, no less. There are some quite scary interfaces in the BCL (although maybe you could argue some are oversized).

I'd say this definitely looks like an acceptable use of interface inheritance.

As an aside... if there is implementation logic that only depends on the interface members, consider using extension methods so that the implementing classes don't need to repeat it... for example:

// just a silly example that only uses members of the target type
public static void DrawComplete(this IDrawableGameObject obj, Canvas canvas) {
   obj.Draw(canvas);
   foreach(var child in obj.Children.OfType<IDrawableGameObject>()) {
       child.DrawComplete(canvas);
   }
}

then all callers get the DrawComplete method without all the implementations having to repeat it.

Marc Gravell
A: 

If you are using IGameObject for this and only this, then maybe consider combining them into one interface. However if you are using IGameObject independently in other areas of your code then what you are doing is perfectly acceptable. There's no reason to duplicate methods and properties in an interface if you can inherit in this fashion.

Alexander Kahoun
A: 

As JaredPar says, there's nothing wrong with interface inheritance in itself; as long as one is a logical base type of the other, it's just an implementation detail. If you can't answer that question simply (Is it always true that an IDrawableGameObject isan IGameObject?), it may be that your model needs some more rethinking. For instance, it might make sense to separate the hierarchy you've created into two independent IUpdateable and IDrawable interfaces; there's nothing preventing a single class from implementing both interfaces.

In either event, if the cast bothers you you might consider keeping a List and a separate List, and adding objects to one or both as they're created. Whether that simplifies your code or complexifies it depends on how everything else is put together.

Skirwan