5

I'm implementing a set of classes and corresponding interfaces where I want each class to have a set of common properties and a set of specialised properties that are specific only to that class. So, I'm considering defining interfaces along the lines of:

interface ICommon {...}  // Members common to all widgets
interface IWidget1 {...} // specialized members of widget type 1
interface IWidget2 {...} // specialized members of widget type 2

I am trying to choose between having the inheritance in the interfaces, or in the class. So, specifically, I can either do it like this:

interface IWidget1 : ICommon {...}
interface IWidget2 : ICommon {...}
class Widget1 : IWidget1 {...}
class Widget2 : IWidget2 {...}

...or like this...

class Widget1: ICommon, IWidget1 {...}
class Widget2: ICommon, IWidget2 {...}

Is there any compelling reason to go one way or the other?

Update: Would it affect the answer if the classes must be COM-visible?

4 Answers 4

6

You should choose interface inheritance if and only if a type implementing IWidget1 must also implement ICommon. In either case, the class is going to implement both IWidget1 and ICommon separately. The only difference is that if you make IWidget1 "derive" from ICommon you enforce the fact that an IWidget1 must also be an ICommon.

A good example is IEnumerable and ICollection. Every ICollection is guaranteed to be IEnumerable, so ICollection derives from IEnumerable. If it was legal or made sense to be a collection but not be enumerable, then implementers of ICollection wouldn't have to implement IEnumerable also.

Whichever you choose will not affect COM visibility. .NET will still export the interfaces separately if I recall correctly.

Sign up to request clarification or add additional context in comments.

2 Comments

Right, yes. All of the Widget types MUST implement ICommon. That's teh reason for it, to enforce its implementation in each and every widget.
Then yeah you definitely should have IWidget1 derive from ICommon.
3

Use Liskov Substitution Principle to help yourself to an answer.

If IWidget1 can be substituted for all clients working in terms of ICommon1, then you could inherit IWidget1 from ICommon1. If not go with the class implementing multiple interfaces.

3 Comments

Doesn't that produce the same result?
@Tim - can you elaborate ? What I meant was that if you can substitute an IWidget1 object for all code expecting an ICommon1 and it makes sense to have a IWidget1 entity in your domain, then you can go with the interface inheritance approach. If not, have the same class implement multiple interfaces.
OK I see what you mean. Thanks.
1

There is another consideration that I think wasn't taken into account in the other answers.

If you derive IWidgetX from ICommon, and then come up with a widget that has the behaviour of both IWidget1 and IWidget2 you can do multiple interface implementation:

class Widget3 : IWidget1, IWidget2

If both were interface were derived from ICommon, then you'll have two implementations of ICommon in your class. That's not a big problem and can be handled by multiple interface implementation, but it changes the logic.

On the other hand, if you don't derive IWidgetX from ICommon, you can just implement all three and not have to deal with explicit implementation:

class Widget3 : IWidget1, IWidget2, ICommon

So, if it's conceivable that you might need such Widget3 class - you'd better not derive the IWidgetX interfaces from ICommon

1 Comment

Thanks Tim - although it turns out that I'm not exactly right! I dug a bit deeper into this multiple interface implementation thing and actually you don't have two implementations of ICommon - if you had, then the cast (ICommon)(new Widget3()) would be unresolvable. I described the situation in more detail in this blog post The argument against deriving IWidgetX from ICommon is still partially valid though
0

The inheritence is dependent on the attribute/behaviour of the class or interface. If the behaviours in IWidget1 and IWidget2 include all of the behaviours in ICommon, then you can surely inherit like IWidget1 : ICommon and IWidget2 : ICommon and there is no issue regarding ComVisible. This is simply OOPS concept.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.