Trying to understand the purpose of interfaces

J

jm

I am having trouble understanding the purposes of an interface, even
though the concept of interfaces is around me all the time (user
interface, for example). I'm just not understanding software
interfaces.

Like anything else, it appears Interfaces are by design something that
requires documentation. I know this may be obvious, but if I have a
class A and I say, well, class A implements IMyInterface. The fact
that it implements IMyInterface is supposed to mean something to me. I
am guessing that MS and other Sun have a lot of well defined and
documented interfaces that I would eventually care about.

I guess I am looking for a time when their absence would require them.
I think that by seeing their missing from a given situation that
requires them (or would be hard without them), I might see and
understand their necessity and understand.

Does anyone have an example of this? I hope this made some sense.

Thank you.
 
M

Mark Wilden

if I have a
class A and I say, well, class A implements IMyInterface. The fact
that it implements IMyInterface is supposed to mean something to me.

What it means is that you can use an object of that class where an object of
type IMyInterface is expected.

Otherwise, it just means that IMyInterface methods/properties are
implemented in the class, but you wouldn't need to use an interface for that
purpose alone.

//ark
 
M

Michael Nemtsev

Hello JM,

Have discussed recently. See there http://petesbloggerama.blogspot.com/2006/10/note-about-c-and-interfaces.html

J> I am having trouble understanding the purposes of an interface, even
J> though the concept of interfaces is around me all the time (user
J> interface, for example). I'm just not understanding software
J> interfaces.
J>
J> Like anything else, it appears Interfaces are by design something
J> that requires documentation. I know this may be obvious, but if I
J> have a class A and I say, well, class A implements IMyInterface. The
J> fact that it implements IMyInterface is supposed to mean something to
J> me. I am guessing that MS and other Sun have a lot of well defined
J> and documented interfaces that I would eventually care about.
J>
J> I guess I am looking for a time when their absence would require
J> them. I think that by seeing their missing from a given situation
J> that requires them (or would be hard without them), I might see and
J> understand their necessity and understand.
J>
J> Does anyone have an example of this? I hope this made some sense.
J>
J> Thank you.
J>
---
WBR,
Michael Nemtsev :: blog: http://spaces.live.com/laflour

"At times one remains faithful to a cause only because its opponents do not
cease to be insipid." (c) Friedrich Nietzsche
 
J

Jeff Louie

jm... Just look at an interface as a contract. Wherever a software
contract would
be useful consider writing an interface. An example is a network
service. You
program to the interface ISomeUsefulNetworkService. Any client can look
up
your service on the network and interact with your particular
implementation of
ISomeUsefulNetworkService as long as you implement
ISomeUsefulNetworkService. Your competitors can also implement their own
network service that implements this interface. To the client, the
actual
implementation details are hidden. The client simply makes calls to the
interface
and can utilize any network service that implements the interface.

Regards,
Jeff
 
G

Guest

Hi jm,
here is a good example, keep reading the first paragraph then you will get
to the bit where interfaces are useful, I could give you a textbook example,
but here is one example that is useful in everyday C# life. With C# you have
garbage collection which is non deterministic, meaning once your objects go
out of scope you cannot say exactly when their underlying resources are going
to be cleaned up, it is up to the garbage collector to decide when this will
happen. This is normally not an issue but when your objects have references
to unmanaged resources such as network connections / database connections /
unmanaged memory allocations etc you want to be able to control that these
resources are cleaned up as soon as you are finished using the object, since
the GC is not aware that these resources are limited and will not know it
should clean up the object ASAP.

..Net has an interface called IDisposable which has a single method "void
Dispose()". The idea being that when this method is called all internal
state is cleaned up, so you can control exactly when network connections / db
conn etc are closed. Now what it means for two different objects to "clean
up" their internal state can be completely different, these objects do not
share any common cleanup code so it makes no sence to make them inherit from
some base class just so they both have the Dispose method, objects that
implement IDisposable can define how objects can be cleaned up inside the
Dispose method, so in code you end up with:

void MyFunction()
{
MyDatabaseObject db = null;
MyCustomMemoryCreator mc = null;

try
{
db = new MyDatabaseObject();
mc = new MyCustomMemoryAllocator();

//do some stuff
}
finally
{
//going out of scope, lets release all unmanaged state
//this is inside the finally since we want to make sure these resources
//are cleaned up even if there is an exception in the function.
if(db != null) db.Dispose();
if(mc != null) mc.Dispose();
}
}

It's kind of a pain to have to use the try / finally each time so you can
use the "using" keyword which takes an object that implements the IDisposable
interface, the objects passed to this language construct may not be related
at all, all this construct knows is that on each object it can call a method
called Dispose() once the current scope of the using statement is exited.


//The following code is semantically equivalent to the above code:
using(MyDatabaseObject db = new MyDatabaseObject())
using(MyCustomMemoryCreator mc = new MyCustomMemoryCreator())
{
//do some work

//Dispose method on each object will automatically get called.
}

So you can see how even though you have objects that need to implement the
same interface i.e. a Dispose method, they may have nothing in common so you
do not want those objects to inherit from a base class since they share NO
common code just a common interface.

Kind of long winded but a good example of why interfaces are useful :)

Mark.
 
B

Bob Jones

Lets say you have a bunch of ducks. You have your mallard, rubber
duckie, etc. Now all these ducks to the same things, but they do them
in different ways. Ducks quack, but mallard's quack is "quack!" and the
rubber duckie's quack is "squeak!" They both swim, but slightly
differently. More over, however, they're all ducks.

You want to implement ducks but C# is a strongly typed language. You
can't write code to handle a mallard and a rubber duckie because
they're different classes - unless you use interfaces.

So you define a "Iduck" interface and list the behaviors (methods) that
all ducks have: swim, quack, fly, etc. Then, when you define each
individual duck class, implementing the Iduck interface, with different
implementations for swim, fly, etc. and then you can write code that
handles "Iducks" and you can give it any old kind of duck - because
they're all ducks (i.e. implementing the same interface) with the same
general duck behaviors (methods).

Note that when a class implements an interface it is somewhat like
inheritance. Please don't anyone start arguing the technical nits here;
as a practical matter you can think in terms of "a mallard is an Iduck"
and that works fine. The neat thing is that a class can implement any
number of interfaces, while it can only inherit from one class. It's
not unusual to see interfaces with no methods defined; it's only
purpose being to handle anything as that general "type".
 
R

Rob Pollard

Interfaces can be used for lots of things:
i. Form a binding contract that a particular class supports a
particular feature.
ii. Can be used for subsystem isolation, especially handy if your
software relies on 3rd party products.
iii. Method filtering. If you have a class with 1000's of methods,
you can use several interfaces with that class so that you can view that
class as it's interface implementation. This has the advantage that
the intellisense only picks up the relevant methods.
iv. Polymorphism (vs Class hierarchy Polymorphism).
v. Some technologies like COM use interfaces exclusively and use it
to black box the internal classes.
vi. Similar to ii above in that they can be used to develop a
Plug'n'Play system, or if you don't want to go that far, they can be used
with class factories to give you maximum flexibility with regard to
switching in and out various subsystems of your application.

There are many more! Interfaces, once you learn them become indispensable.

If you want me to elaborate on any of the above, I'd be happy to. I
personally find them very handy.
 
P

Peter Thornqvist

Here's a (close to) real world example:

Your manager gives you the following task: "I need a combobox that is
synchronized with a TabControl such that when an item is added to the
combobox, a tab is added to the tabcontrol, when an item is deleted from the
combobox, the matching tab is deleted from the tabcontrol and when an item
is selected in the combobox, the matching tab is selected in the tabcontrol.
I need it yesterday."

Now you can solve this problem by deriving a new control from ComboBox and
add code to manipulate a TabControl directly (for example, you add a
TabControl property to your ComboBox, override the Add, Delete and Change
methods and add, remove, change tabs if the property is assigned) and you
would be finished quite soon (although not yesterday). This is inheritance
and all is good.

The next day your manager comes in to you and say "Ok, that looks nice, but
we really need to do something about that TabControl, it looks boring. I've
found this really cool, whiz-bang TabControl that I've payed good $$$'s for
and the best thing is that it isn't derived from the MS TabControl, so it is
a lot better by default" (this is his way to try to be "in" with the
coders - he once attended a manager meeting where he was told that all
coders hate MS). You sigh and start to implement a new ComboBox that can
connect to the whiz-bang TabControl (you are keeping the other one around
just in case - you are a seasoned developer and not stupid).

You now have two different ComboBoxes that does the same thing with two
different TabControls. You feel that all is not so good anymore and you hope
that your manager doesn't come into your room tomorrow with another
whiz-bang control (like a really cool ComboBox that isn' t derived from the
MS ComboBox) or even a whole new set of controls he wants to synchronize.
You are probably not so lucky and you wish there was some other way to solve
this problem. There is. Use interfaces.

So how do you solve this problem using interfaces? Well, you start by
defining the behavior that is required (Add, Delete, Change methods comes to
mind) and you put them in an interface. Let's call it IControlSync:

public interface IControlSync
{
public int Add(string Value);
public void Delete(int Index);
public void Change(int Index);
}

You now proceed to derive a new control from ComboBox and add an
IControlSync property to it. Whenever Add, Delete and Change is called in
your ComboBox, you call the appropriate IControlSync interface method (if it
has been assigned, of course). You don't know what type of control you are
calling (or if it is a control at all), you are just calling the
IControlSync methods. That is all you know and that is all you need to know.
You obviously also derive a new control from TabControl that *implements*
the IControlSync methods. You must also assign this new control to the
IControlSync property of the ComboBox (I assume you knew that already).

Now, when the boss comes in the second day (remember?) and wants to use his
new TabControl, you just smile smuggly, install the whiz-banger, derive a
new TabControl from it and quickly implement the IControlSync methods. When
done, you just assign the new TabControl to the ComboBox IControlSync
property to make them synch.

Now imagine the possibilities if the ComboBox also implements IControlSync
and the TabControl had an IControlSync property. You would have several
different controls that can be synchronized with each other in any which way
you like by just assigning to the appropriate IControlSync property.

Whenever a control needs the same functionality, you just derive a new
control and implement the IControlSync methods on it. As a bonus, since
IControlSync has nothing to do with the class it is implemented on, the
implementor can be *any* class, not just a Control (the name was chosen to
confuse noobs).

Hope that "spins" it for you.
 
X

xlar54

All excellent examples. I would like to piggyback the OP and ask about
real world examples of RETURNING an interface. I have seen code that
does as such:

public ISomething Somemethod()
{
....do work
return SomeObject;
}

or some such. What I read from this is that the calling code must
assign the return value to any object which has an ISomething
interface? Such as:

ISomething varsGettingHardToDescribe = Somemethod();

But the returning object loses it's inherent SomeObject class methods.
Ive seen (something like) this before, and have trouble at times
following whats going on, what is gained, and what is lost.
 
B

Bruce Wood

jm said:
I am having trouble understanding the purposes of an interface, even
though the concept of interfaces is around me all the time (user
interface, for example). I'm just not understanding software
interfaces.

Like anything else, it appears Interfaces are by design something that
requires documentation. I know this may be obvious, but if I have a
class A and I say, well, class A implements IMyInterface. The fact
that it implements IMyInterface is supposed to mean something to me. I
am guessing that MS and other Sun have a lot of well defined and
documented interfaces that I would eventually care about.

I guess I am looking for a time when their absence would require them.
I think that by seeing their missing from a given situation that
requires them (or would be hard without them), I might see and
understand their necessity and understand.

Does anyone have an example of this? I hope this made some sense.

Thank you.

This question comes up with some regularity in this newsgroup. Try
searching for "interface" in the archives. Here is one thread I found
from a while back:

http://groups.google.com/group/micr...ges.csharp/browse_frm/thread/22487039d5505a47
 
P

Peter Thornqvist

But the returning object loses it's inherent SomeObject class methods.
Ive seen (something like) this before, and have trouble at times
following whats going on, what is gained, and what is lost.

The reason to return an interface is so the caller gets an instance that
implements an interface without knowing what object does the implementation.
It is very similar to the IControlSync property of the ComboBox in my
example:

comboBox1.ControlSync = tabControl1;

Although we in this example know the object that implements IControlSync,
that is not always the case. Think about a factory class that can create
different implementing instances based on some type of parameter or other
means:

public interface IWebDownloader
{
string GetFileContent(string URL);
}

private class HttpDownloader:IWebDownloader
{
string GetFileContent(string URL)
{
// implementation here
}
}

private class FtpDownloader:IWebDownloader
{
string GetFileContent(string URL)
{
// implementation here
}
}

static class WebDownloaderFactory
{
public IWebDownloader GetWebDownloader(string Protocol)
{
if (Protocol.Equals("http")
return new HttpDownloader();
else if (Protocol.Equals("ftp")
return new FtpDownloader();
else
return null; // protocol not supported
}
}

You call it like this:

IWebDownloader wd = WebDownloaderFactory.GetWebDownloader("ftp");
if (wd != null)
string s = wd.GetFileContent("ftp.microsoft.com/somefile.txt");

You don't know which implementation you are getting, just that it supports
IWebDownloader. By using interfaces you are decoupling your code from the
IWebDownloader implementations, making your program more flexible and at the
same time more robust.
 
J

Jon Skeet [C# MVP]

This question comes up with some regularity in this newsgroup.

You're right. Sounds like another topic to write an article about at
some point. If I do so, I'd welcome reviewers/contributions from
others...

(I have another article in progress about the differences between value
types and reference types. It's maddeningly difficult to explain
accurately and simply.)
 
J

jm

Thank you.

Why wouldn't I have an abstract class and override the abstract method,
since all the obects inherit from the same top level object (ducks)?
 
J

jm

Peter said:
Here's a (close to) real world example:

Your manager gives you the following task: "I need a combobox that is
synchronized with a TabControl such that when an item is added to the
combobox, a tab is added to the tabcontrol, when an item is deleted from the
combobox, the matching tab is deleted from the tabcontrol and when an item
is selected in the combobox, the matching tab is selected in the tabcontrol.
I need it yesterday."

Now you can solve this problem by deriving a new control from ComboBox and
add code to manipulate a TabControl directly (for example, you add a
TabControl property to your ComboBox, override the Add, Delete and Change
methods and add, remove, change tabs if the property is assigned) and you
would be finished quite soon (although not yesterday). This is inheritance
and all is good.

The next day your manager comes in to you and say "Ok, that looks nice, but
we really need to do something about that TabControl, it looks boring. I've
found this really cool, whiz-bang TabControl that I've payed good $$$'s for
and the best thing is that it isn't derived from the MS TabControl, so it is
a lot better by default" (this is his way to try to be "in" with the
coders - he once attended a manager meeting where he was told that all
coders hate MS). You sigh and start to implement a new ComboBox that can
connect to the whiz-bang TabControl (you are keeping the other one around
just in case - you are a seasoned developer and not stupid).

You now have two different ComboBoxes that does the same thing with two
different TabControls. You feel that all is not so good anymore and you hope
that your manager doesn't come into your room tomorrow with another
whiz-bang control (like a really cool ComboBox that isn' t derived from the
MS ComboBox) or even a whole new set of controls he wants to synchronize.
You are probably not so lucky and you wish there was some other way to solve
this problem. There is. Use interfaces.

So how do you solve this problem using interfaces? Well, you start by
defining the behavior that is required (Add, Delete, Change methods comes to
mind) and you put them in an interface. Let's call it IControlSync:

Okay. This I understand so far. Makes sense and had I not heard of
"interfaces" I would probably have done it this way forever.

public interface IControlSync
{
public int Add(string Value);
public void Delete(int Index);
public void Change(int Index);
}

You now proceed to derive a new control from ComboBox and add an
IControlSync property to it. Whenever Add, Delete and Change is called in
your ComboBox, you call the appropriate IControlSync interface method (if it
has been assigned, of course). You don't know what type of control you are
calling (or if it is a control at all), you are just calling the
IControlSync methods. That is all you know and that is all you need to know.


Alright, this is where I begin to be lost. In my mind I see this:

class MyClass : ComboBox, IControlSync
{
public void Add (string Value)
{
//do something
}
public voic Delete (int Index)
{
//do something
}
....
}

Now if I had a regular ComboBox and did not inherit from it to make a
control. We are saying it has its own "normal" Add, Delete, and
Change, but because I need to do something other than what those
methods normally do I use the Interface that has its own signature for
Add, Delete, & Change. We are also saying that I cannot "override" the
ComboBox methods right? I mean that's why I don't need to know
anything about the ComboBox control whether it has a virtual method or
not. I only know it has the IControlSync interface.

So are you saying that because ComboBox has and Add, Delete, and
Change, and I expect that from working with it in the past (in this
scenario; I really don' t know.) I can just implement the interface
and the new signatures just "take over" the definition of what those
methods should be?

You obviously also derive a new control from TabControl that *implements*
the IControlSync methods. You must also assign this new control to the
IControlSync property of the ComboBox (I assume you knew that already).

Not really. Just barely hanging on actually. But I am sure it's
obvious (sooner or later).

class MyNewTabContro : TabControl, IControlSync
{
//not sure what assign this new control to the IControlSync property
//of the ComboBox means
}
Now, when the boss comes in the second day (remember?) and wants to use his
new TabControl, you just smile smuggly, install the whiz-banger, derive a
new TabControl from it and quickly implement the IControlSync methods. When
done, you just assign the new TabControl to the ComboBox IControlSync
property to make them synch.

Now imagine the possibilities if the ComboBox also implements IControlSync
and the TabControl had an IControlSync property. You would have several
different controls that can be synchronized with each other in any which way
you like by just assigning to the appropriate IControlSync property.

Whenever a control needs the same functionality, you just derive a new
control and implement the IControlSync methods on it. As a bonus, since
IControlSync has nothing to do with the class it is implemented on, the
implementor can be *any* class, not just a Control (the name was chosen to
confuse noobs).

Well, I guess I was just wrong above.


Hope that "spins" it for you.

I almost understand. Thanks again (to everyone.) I'll keep thinking
about it.
 
P

Peter Thornqvist

Alright, this is where I begin to be lost. In my mind I see this:
class MyClass : ComboBox, IControlSync
{
public void Add (string Value)
{
//do something
}
public voic Delete (int Index)
{
//do something
}
...
}

Actually it should look more like this:

class MyCombo: ComboBox

{
private IControlSync _ControlSync = null;
public IControlSync ControlSync
{
get { return _ControlSync; }
set { ControlSync = value; }
}
public void Add(string Value): base (Value)
{
if (ControlSync != null)
ControlSync.Add(Value);
}
...
}
Not really. Just barely hanging on actually. But I am sure it's
obvious (sooner or later).

public class MyTabControl: TabControl, IControlSync
{
private void IControlSync.Add(string Value)
{
// code to add a new tab to the tab control
}
private void IControlSync.Delete(int Index)
{
// code to remove tab at Index
}
...
}
I almost understand. Thanks again (to everyone.) I'll keep thinking
about it.

You'll get it eventually. we all do :)
 
P

Peter Thornqvist

Just to be clear: there is no Add() method in ComboBox (it's actually part
of the Items collection). I am just using it as a simplified model to
explain the concept.
 
B

Bruce Wood

jm said:
Thank you.

Why wouldn't I have an abstract class and override the abstract method,
since all the obects inherit from the same top level object (ducks)?

Here you've hit upon why interfaces are useful in a single-inheritance
language.

What if you need to give the same capability to a wide range of objects
that aren't related by inheritance? In a single-inheritance language I
have two choices.

1. Twist the inheritance hierarchy. I can stick the functionality
somewhere in the existing hierarchy, or insert a new class that
contains that functionality somewhere in the hierarchy. Inevitably this
leads to classes that shouldn't have the functionality getting it
(because they inherit from some class for some reason other than
getting this functionality), and some classes that should have the
functionality not getting it (because they're elsewhere in the
hierarchy for some reason).

Take the duck example that was given by another poster. Do you really
want a RubberDuck inheriting from Duck? What if Duck inherits from
FlyingBird which inherits from Bird which inherits from Mammal?
RubberDucks can't fly, and they're not mammals. That's what I mean by
"twisting the inheritance hierarchy": do I shoehorn things in where
they logically don't belong just so that they can get some
functionality, just so that I can treat them as equivalent in certain
cases?

2. The other choice is to insert the functionality piecemeal. Write a
Quack method in RubberDuck, even though it doesn't inherit from Duck
and therefore the compiler has no way to know that the Duck.Quack()
method and the RubberDuck.Quack() method are semantically equivalent:
they do the same thing to disparate objects. Then I have to write ugly
code like this:

public void SoundAWarning(object thing)
{
Duck duckThing = thing as Duck;
if (duckThing != null)
{
duckThing.Quack();
}
else
{
RubberDuck rubberDuckThing = thing as RubberDuck;
if (rubberDuckThing == null)
{
throw new ArgumentException(String.Format("Argument must be
either Duck or RubberDuck, not {0}.", thing.GetType()), "thing");
}
else
{
rubberDuckThing.Quack();
}
}
}

What interfaces allow me to do is give the same functionality to
otherwise unrelated classes. With an IQuack interface definition, I can
do this:

public interface IQuack
{
void Quack();
}

public class Duck : FlyingBird, IQuack
{
public void Quack() { ... }
}

public class RubberDuck : WaterToy, IQuack
{
public void Quack() { ... }
}

Notice that RubberDuck isn't a Duck: it's a WaterToy, because that's
where it logically belongs in my inheritance hierarchy. However, it
shares some functionality with Duck, so I can write methods like this:

public void SoundAWarning(IQuack quacker)
{
quacker.Quack();
}

and this (admittedly silly) method doesn't need to know whether it was
passed a Duck (a living creature) or a RubberDuck (a water toy). All it
needs to know is that the object passed it is capable of quacking in
some fashion or other. So, SoundAWarning accepts a group of objects
that cuts across the inheritance hierarchy in an arbitrary way.

Now, this may seem a nicety until you realize that all of this is
understood by and enforced by the compiler. Now that you've told the
compiler that SoundAWarning accepts only objects that implement IQuack,
the compiler will check that you only ever pass it a Duck or a
RubberDuck (or something that inherits from either of these) and
nothing else. If you recall my ugly original SoundAWarning method
above, it took an "object" as its argument, effectively telling the
compiler, "allow the caller to pass me anything at all, and I'll figure
out if it's valid at runtime." You've moved a validity check from
runtime to compile time, and you have tighter, cleaner, clearer code.
It's all good.
 
J

jm

Bruce said:
Here you've hit upon why interfaces are useful in a single-inheritance
language.

What if you need to give the same capability to a wide range of objects
that aren't related by inheritance? In a single-inheritance language I
have two choices.

1. Twist the inheritance hierarchy. I can stick the functionality
somewhere in the existing hierarchy, or insert a new class that
contains that functionality somewhere in the hierarchy. Inevitably this
leads to classes that shouldn't have the functionality getting it
(because they inherit from some class for some reason other than
getting this functionality), and some classes that should have the
functionality not getting it (because they're elsewhere in the
hierarchy for some reason).

Take the duck example that was given by another poster. Do you really
want a RubberDuck inheriting from Duck? What if Duck inherits from
FlyingBird which inherits from Bird which inherits from Mammal?
RubberDucks can't fly, and they're not mammals. That's what I mean by
"twisting the inheritance hierarchy": do I shoehorn things in where
they logically don't belong just so that they can get some
functionality, just so that I can treat them as equivalent in certain
cases?

2. The other choice is to insert the functionality piecemeal. Write a
Quack method in RubberDuck, even though it doesn't inherit from Duck
and therefore the compiler has no way to know that the Duck.Quack()
method and the RubberDuck.Quack() method are semantically equivalent:
they do the same thing to disparate objects. Then I have to write ugly
code like this:

public void SoundAWarning(object thing)
{
Duck duckThing = thing as Duck;
if (duckThing != null)
{
duckThing.Quack();
}
else
{
RubberDuck rubberDuckThing = thing as RubberDuck;
if (rubberDuckThing == null)
{
throw new ArgumentException(String.Format("Argument must be
either Duck or RubberDuck, not {0}.", thing.GetType()), "thing");
}
else
{
rubberDuckThing.Quack();
}
}
}

What interfaces allow me to do is give the same functionality to
otherwise unrelated classes. With an IQuack interface definition, I can
do this:

public interface IQuack
{
void Quack();
}

public class Duck : FlyingBird, IQuack
{
public void Quack() { ... }
}

public class RubberDuck : WaterToy, IQuack
{
public void Quack() { ... }
}

Notice that RubberDuck isn't a Duck: it's a WaterToy, because that's
where it logically belongs in my inheritance hierarchy. However, it
shares some functionality with Duck, so I can write methods like this:

public void SoundAWarning(IQuack quacker)
{
quacker.Quack();
}

and this (admittedly silly) method doesn't need to know whether it was
passed a Duck (a living creature) or a RubberDuck (a water toy). All it
needs to know is that the object passed it is capable of quacking in
some fashion or other. So, SoundAWarning accepts a group of objects
that cuts across the inheritance hierarchy in an arbitrary way.

Now, this may seem a nicety until you realize that all of this is
understood by and enforced by the compiler. Now that you've told the
compiler that SoundAWarning accepts only objects that implement IQuack,
the compiler will check that you only ever pass it a Duck or a
RubberDuck (or something that inherits from either of these) and
nothing else. If you recall my ugly original SoundAWarning method
above, it took an "object" as its argument, effectively telling the
compiler, "allow the caller to pass me anything at all, and I'll figure
out if it's valid at runtime." You've moved a validity check from
runtime to compile time, and you have tighter, cleaner, clearer code.
It's all good.

Very helpful. I see what you are saying and understand. This makes
sense on why it is adventageous to use an Interface, in this case. I
still have yet to use them myself, but I do understand.

Do interfaces get used in ASP.NET or is that more of an executable
world?

Thank you.
 
J

jm

Bruce said:
Here you've hit upon why interfaces are useful in a single-inheritance
language.

What if you need to give the same capability to a wide range of objects
that aren't related by inheritance? In a single-inheritance language I
have two choices.

1. Twist the inheritance hierarchy. I can stick the functionality
somewhere in the existing hierarchy, or insert a new class that
contains that functionality somewhere in the hierarchy. Inevitably this
leads to classes that shouldn't have the functionality getting it
(because they inherit from some class for some reason other than
getting this functionality), and some classes that should have the
functionality not getting it (because they're elsewhere in the
hierarchy for some reason).

Take the duck example that was given by another poster. Do you really
want a RubberDuck inheriting from Duck? What if Duck inherits from
FlyingBird which inherits from Bird which inherits from Mammal?
RubberDucks can't fly, and they're not mammals. That's what I mean by
"twisting the inheritance hierarchy": do I shoehorn things in where
they logically don't belong just so that they can get some
functionality, just so that I can treat them as equivalent in certain
cases?

2. The other choice is to insert the functionality piecemeal. Write a
Quack method in RubberDuck, even though it doesn't inherit from Duck
and therefore the compiler has no way to know that the Duck.Quack()
method and the RubberDuck.Quack() method are semantically equivalent:
they do the same thing to disparate objects. Then I have to write ugly
code like this:

public void SoundAWarning(object thing)
{
Duck duckThing = thing as Duck;
if (duckThing != null)
{
duckThing.Quack();
}
else
{
RubberDuck rubberDuckThing = thing as RubberDuck;
if (rubberDuckThing == null)
{
throw new ArgumentException(String.Format("Argument must be
either Duck or RubberDuck, not {0}.", thing.GetType()), "thing");
}
else
{
rubberDuckThing.Quack();
}
}
}

What interfaces allow me to do is give the same functionality to
otherwise unrelated classes. With an IQuack interface definition, I can
do this:

public interface IQuack
{
void Quack();
}

public class Duck : FlyingBird, IQuack
{
public void Quack() { ... }
}

public class RubberDuck : WaterToy, IQuack
{
public void Quack() { ... }
}

Notice that RubberDuck isn't a Duck: it's a WaterToy, because that's
where it logically belongs in my inheritance hierarchy. However, it
shares some functionality with Duck, so I can write methods like this:

public void SoundAWarning(IQuack quacker)
{
quacker.Quack();
}

and this (admittedly silly) method doesn't need to know whether it was
passed a Duck (a living creature) or a RubberDuck (a water toy). All it
needs to know is that the object passed it is capable of quacking in
some fashion or other. So, SoundAWarning accepts a group of objects
that cuts across the inheritance hierarchy in an arbitrary way.

Now, this may seem a nicety until you realize that all of this is
understood by and enforced by the compiler. Now that you've told the
compiler that SoundAWarning accepts only objects that implement IQuack,
the compiler will check that you only ever pass it a Duck or a
RubberDuck (or something that inherits from either of these) and
nothing else. If you recall my ugly original SoundAWarning method
above, it took an "object" as its argument, effectively telling the
compiler, "allow the caller to pass me anything at all, and I'll figure
out if it's valid at runtime." You've moved a validity check from
runtime to compile time, and you have tighter, cleaner, clearer code.
It's all good.

This may be dumb, but say I had some method that took the parameter:

public void RunAppliance (IOutlet electricalAppliance)
{
electicalAppliance.TurnOn();
}

As long as the electicalAppliance class reference sent to the method
RunAppliance implements the IOutlet interface then objects like::

refrigerator
toaster
tvset

all can/must use the method TurnOn() in there respective classes. Now
if I knew every single electrical appliance that would ever be designed
had a TurnOn() method, then I may not need the Interface, but if I did
not have the Inteface, then I would have to do something like you did
above with (object electricalAppliance) and do all sorts of tests on
every single possible appliance.

Because I have an Interface I, a) know the contract and that anything
that implements the IOutlet interface must have a TurnOn() method, b)
because of this I can created a reference like (IOutlet
electricalAppliance) and be sure at compile time all reference are
"clean."

The advantage, I'm sure there are others, is in the ability to not have
know every single thing about a given class except that it implements
IOutlet and therefore all these otherwise unrelated classes now have
something in common. They implement the same interface.

This also helps me kind of see why there are muliple interfaces that
can be implemented. I can see why some or all appliances might turn
on, but not all heat up. A stove and toaster might have a IHeatUp
inteface, but a refrigator probably won't. We need these unique but
properties and methods for the uninherited classes that are not related
in a hierachy, but they are related in a implementation. They all do
something called the same thing, just differently.

I think I'm still missing some of it, but I think I have a better
understanding of it. Sorry if I repeated myself too much and being
long winded. It was more for me than anything. Hopefully some of it
is even right!
 

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