interface vs. inheritance

H

Hazz

Are there any good references/articles/books which provide clarity toward my
insecurity still on deciding how to model a complex system? I still feel
uncomfortable with my understanding, even though I have worked with these
systems on when to decide to use interfaces (and how they should be
developed) as opposed to or complemented by the use of inheritance from base
classes.
If I am thinking from the point of view of some specific activity and I
begin to think at the method level, how do I think about its implementation
at a code syntax level as to whether that method is obtained through
inheritance from a base class, or if I obtain it via an interface which I
have also inherited from?
Thank you. -hazz
 
S

sadhu

I tend to follow this guideline. If the relationship is clearly "is-a",
I use inheritance. If it is more like "can-be", I use interfaces. For
eg, TextBox "is-a" Control, ArrayList "can-be" enumerated (so it
implements IEnumerable). In general, if an object can be treated in
different ways (can be enumerated, can be cloned..), I implement
interfaces.

And obviously, if you're going to use existing functionality AND extend
it, I derive from it.

Regards
Senthil
 
H

Hazz

Thank you so much for that very simple explanation Senthil. I think I get
that. I have to think a bit more about the "can-be" relationships.

Also as you stated, that if you are merely extending existing functionality,
you derive from it.
By that I assume you mean the other role of interfaces? ie. as a contract
with the underlying classes which they represent whose purpose is to provide
the freedom to change the underlying code without having to change the
interface ??? Wait a minute. In a project build I still have to rebuild the
whole solution with different projects whether they contain interfaces with
their associated classes or just the classes without any interface to
represent them, right? If the code changes in a class and I want to use it
somewhere outside of that namespace where it is referred to, I have to
rebuild the whole project so that Visual Studio (and my consumer class) will
recognize the new functionality.

Now I am getting into the reference dilemma which I puzzle over a bit on
complex projects ie. circular references, build problems where sometimes a
solution with many projects needs to be decomposed into smaller builds to
build without error.

If I create a project/namespace with a certain scope, like "datalayer" and
another, "application specific support utilities," then why would I use
interfaces to represent the classes contained in these projects? If I extend
the functionality of the application using either of these two different
examples, couldn't I equally inherit the interface by the 'class :
interface' syntax or by the 'using' statement? Both require I set a
reference prior to using them and both require I rebuild after any changes
are made to any of the participant classes. What I am getting at is that I
don't see how interfaces add any advantage here for extending functionality?
Is it because I can inherit from multiple interfaces? I still don't buy that
because I could just add one more 'using' statement and grab another
namespace with its underlying classes and not have to mess at all with the
time it takes to create an interface.

thanks for any clarification if I haven't absolutely lost you. ;-) It is o.k
to say my question makes absolutely no sense or I am dead wrong about my
understanding. -hazz
 
J

Jeff Louie

1)Favor containment.
2)Avoid extending a class unless it was designed to be extended.
3)If you have a well defined contract that will be implemented by many
classes use an interface. An interface represents a purely abstract IS_A
relationship.
4)If the contract is evolving, consider using a base class so that you
can provide default implementations of any new methods so that clients
that use your base class can be recompiled without breaking.
5)Use a base class if you need to include implementation details.

That said... every time I try to solve a problem I seem to start by
describing the contract with an interface say IVersionable. Then I end
up writing an abstract class with default implementations as in
AbstractVersion. Then I end up creating concrete classes based on the
Abstract class as in Version : AbstractVersion.

So I would try this pattern: Interface -- AbstractInterface -- Class
which uses both interfaces and base classes and offers both options to
the user of the "interface/class."

Regards,
Jeff
 
H

Hazz

Thank you Jeff. I am digesting this. It's a big meal. As my Dad used to say,
my eyes are bigger than my stomach.

Just a bit of qualification of what you mean by;

1 Avoid extending a class unless it was designed to be extended?
a) what's one bad idea that would make it a bad idea with an eye toward
extending.

b) one good idea with an eye toward extension.

and

2. Use a base class if you need to include implementation detail
a) you mean implementation details get fleshed out in the derived classes?
Or are you saying certain implementation details should be in the base class
as opposed to somewhere else?

I really appreciate the your responses. Fortunately I wasn't the architect
on a recent project but I found out you can be thrown into a lego pond and
still expect to hook a few things up. -hazz
 
R

Rachel Suddeth

I'm certainly no guru, but I've been taking the pragmatic view.

1) You can only inherit code from one base class, but you can implement as
many interfaces as you wish.
2) You have to write code for every interface member, even if the code to
implement it in every class is the same.

In the work I've done so far, it hasn't been too difficult to figure out
when I can write a lot of useful code in a base class, and simply inherit
it, and when most of the methods would have to be overridden anyway, so it
isn't that much more work to have an interface. We save inheritance for the
cases where it's really useful. This has meant writing throwaway code (and
actually throwing it away -- after chopping out the useful bits and putting
them where they really belong), but that's how you learn to program.

And yes, as someone else mentioned, don't forget about containing things. I
have found events very useful for that. If there is a set of functionality I
might like to inherit, but can't because I'm already inheriting from
something else, and I have only a couple methods that would need overrides
(if I were able to inherit from it), then I can create a class that exposes
those methods as events. Then my main class can get the functionality by
having a variable of that type... maybe setting some properties to tell it
what it needs to know about the main class, and handle the events rather
than overriding methods.

-Rachel
 
J

Jeff Louie

Hi Hazz... Inline
a) what's one bad idea that would make it a bad idea with an eye toward
extending.<
If you have a verified collection class that is not designed to be
extended and a user of your class adds setters and getters that do not
verify and corrupt the collection. So inheritance breaks encapsulation.
one good idea with an eye toward extension.<
An AbstractVersion class with an == operator and a default virtual
Equals method designed to be overridden by the user. The user can
override the Equals method, thus changing the implementation of the ==
operator!
a) you mean implementation details get fleshed out in the derived
classes? Or are you saying certain implementation details should be in
the base class as opposed to somewhere else?<

C# only supports single inheritance of implementation so your choices
are to extend from a class with implementation or contain a class with
implementation and forward (delegate) calls to the contained class or
just write all the implementation from scratch.

Now the interesting decision is if you should extend from an incomplete
class or define a method that takes an interface that defines the
incomplete methods. So if you have a generic sort routine that is
incomplete and requires a Compare method specific to a user class you
can either create an abstract class with an abstract Compare method or
you can declare a Sort method that takes an IComparable object. In the
first case the user extends the AbstractClass and provides a concrete
Compare method. In the second case the use creates a class that
implements IComparable with a Compare method and passes the IComparable
obect to the Sort method. So
1) MySortableCollection : AbstractSortableCollection
mySortableCollection.Sort()
2) MyComparableClass : IComparable
mySortableCollection.Sort(myComparableClass)


Regards,
Jeff
 
H

Hazz

Absolutely fascinating. Events as another means of reuse. Legos supreme. I
don't understand that yet but maybe it has to do with the delegate or type
safe function pointer which allows a level of indirection to sidestep the
inheritance constraints. You mean I am going to have to learn how to wire up
my own events rather than limit myself to only those times when Visual
Studio does it for me automagically?

So interfaces allow you to flatten the structure?...to inherit useful
functionality by virtue of interface multiple inheritance.
Interfaces allow you to compose if you understand which role each member of
the band plays. I can create new members for my band, adding a horn section
if need be.
And inheritance being the vertical dimension where I can think about things
like, "o.k., by adding more generally used functionality higher up the
hierarchy with the base being highest, then its about using the most derived
class, the lowest member, to be consumed by most clients typically becuase I
have something useful to offer. If I do it right, maintainability is
achieved when I can change some functionality high up the chain in one place
rather than having to fly all over the landscape having to touch down
everywhere there is a component which inherited from it. Maybe just by
adding a constructor with another signature to pass an additional parameter
up the ctor chain, I can make adjustments to my application without really
doing any major design damage. The idea is to be creative right? And we can
have fun doing this? Thanks Rachel.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top