Trying to understand interfaces

R

RSH

Hi,

I have been reading on interfaces working on samples I've run across on the
web. For the life of me I cannot seem to grasp them.

It appears to me that interfaces are simply blueprints to a class, that when
implemented, they require the implementing calss to make sure that each of
the properties, functions etc. are handled by the class. (????)

What I am really having a problem with is how they overcome the limitation
of multiple inheritance? It would appear that interfaces simply require that
a class handles a predetermined number of properties events etc. So if I
have a class that implements an interface and I need to add functionality to
that class...I still have to add it to the interface and handle it in the
initial class...this seems redundant to me. Not to mention modifying the
interface to include the new required functionality, now makes all other
classes that implement the interface "break" and now require that I modify
all classes that implement the interface to handle the newly added
functionality.

Now I openly admit I am no OOP guru, and I am simply trying to understand
interfaces...I am certainly not bashing them.

The code below illustrates my initial attempt at understanding
interfaces...pieced together from a few tutorials on the web.



The classes and intefaces apper below. and the instantiation of the objects
appears at the top...and will probably shed light on my lack of
understanding of interfaces.

The first instantiation illustrates the use of the interfaces:
public partial class _Default : System.Web.UI.Page

{

protected void Page_Load(object sender, EventArgs e)

{

IPencil p = new Pencil();

p.Type = "Pencil";

IPencil mp = new MechanicalPencil();

mp.Type = "MechanicalPencil";

IPencil pen = new Pen();

pen.Type = "Pen";

PencilSharpener sharpener = new PencilSharpener();

sharpener.Sharpen(p);

sharpener.Sharpen(mp);

sharpener.Sharpen(pen);

}



Now where I get confused is that I can quite simply get the same results by
bypassing the interfaces and never calling the PencilSharpener class:

protected void Page_Load(object sender, EventArgs e)

{

IPencil p = new Pencil();

p.Type = "Pencil";

p.OnSharpened();

IPencil mp = new MechanicalPencil();

mp.Type = "MechanicalPencil";

IPencil pen = new Pen();

pen.Type = "Pen";

//PencilSharpener sharpener = new PencilSharpener();

//sharpener.Sharpen(p);

//sharpener.Sharpen(mp);

//sharpener.Sharpen(pen);

}



So this is where my paridigm needs some shifting :)

Can you please help shed some light on this? Thank you very much!

Ron








// Interfaces +++++++++++++++++++++++++++++++++

//Pencil Interface

public interface IPencil

{

string Type { get; set; }

int CurrentSharpness { get; set; }

bool IsSharp { get; }

void Write();

void OnSharpened();

}

//Pencil Sharpener Interface

public interface IPencilSharpener

{

void Sharpen(IPencil pencil);

}







// Classes +++++++++++++++++++++++++++++++++++++

// Pencil Class

public class Pencil : IPencil

{

private string m_message;

private string m_sharpenedMessage;

private string m_type;

private int m_currentSharpness;

private int m_charsUsed;

private Boolean m_Sharpened = false;

// Constructor

public Pencil()

{

m_type = string.Empty;

m_currentSharpness = 0;

m_message = string.Empty;

m_sharpenedMessage = string.Empty;

m_charsUsed = 0;

}

// Property

public string Message

{

get { return m_message; }

}

// Property

public string SharpenedMessage

{

get { return m_sharpenedMessage; }

}

// Property

public string Type

{

get { return m_type; }

set {

m_type = value;

m_message = "This is my " + m_type + " writing away!";

m_sharpenedMessage = "This is one sharp " + m_type + "!";

}

}

// Property

public int CurrentSharpness

{

get { return m_currentSharpness; }

set { m_currentSharpness = value; }

}

// Property

public bool IsSharp

{

get { return m_charsUsed <= m_currentSharpness; }

}

// Function

public void Write()

{

foreach (char c in m_message)

{

if (m_Sharpened == false)

{

if (IsSharp)

{

HttpContext.Current.Response.Write(c);

}

else

{

HttpContext.Current.Response.Write("#");

}

}

else

{

HttpContext.Current.Response.Write(c);

}

m_charsUsed++;

}

HttpContext.Current.Response.Write("<BR>");

}

// Function

public void OnSharpened()

{

while(this.m_currentSharpness < m_message.Length)

{

m_charsUsed = 0;

m_currentSharpness++;

Write();

}

m_Sharpened = true;

m_message = m_sharpenedMessage;

Write();

}

public void Sharpen(IPencil pencil)

{

pencil.OnSharpened();

}

}



// Pencil Sharpener Class

public class PencilSharpener : IPencilSharpener

{

public void Sharpen(IPencil pencil)

{

HttpContext.Current.Response.Write("<br>Begin sharpening " + pencil.Type +
"...<br>");

pencil.OnSharpened();

}

}

// Pen Class

class Pen : IPencil

{

private string m_message;

private string m_sharpenedMessage;

private string m_type;

private int m_currentSharpness;

private int m_charsUsed;

private Boolean m_Sharpened = false;

// Constructor

public Pen()

{

m_type = string.Empty;

m_currentSharpness = 0;

m_message = string.Empty;

m_sharpenedMessage = string.Empty;

m_charsUsed = 0;

}

// Property

public string Message

{

get { return m_message; }

}

// Property

public string SharpenedMessage

{

get { return m_sharpenedMessage; }

}

// Property

public string Type

{

get { return m_type; }

set { m_type = value; }

}

// Property

public int CurrentSharpness

{

get { return m_currentSharpness; }

set { m_currentSharpness = 0; }

}

// Property

public bool IsSharp

{

get { return m_charsUsed <= m_currentSharpness; }

}

public void Write()

{

HttpContext.Current.Response.Write(m_message + "<BR>");

}

// Function

public void OnSharpened()

{

m_Sharpened = true;

m_message = "A Pen cannot be sharpened!.";

Write();

}

}





// Mechanical Pencil Class

class MechanicalPencil : IPencil, IPencilSharpener

{

private string m_message;

private string m_sharpenedMessage;

private string m_type;

private int m_currentSharpness;

private int m_charsUsed;

private Boolean m_Sharpened = false;

// Constructor

public MechanicalPencil()

{

m_type = string.Empty;

m_currentSharpness = 0;

m_message = string.Empty;

m_sharpenedMessage = string.Empty;

m_charsUsed = 0;

}

// Property

public string Message

{

get { return m_message; }

}

// Property

public string SharpenedMessage

{

get { return m_sharpenedMessage; }

}

// Property

public string Type

{

get { return m_type; }

set { m_type = value; }

}

// Property

public int CurrentSharpness

{

get { return m_currentSharpness; }

set { m_currentSharpness = value; }

}

// Property

public bool IsSharp

{

get { return m_charsUsed <= m_currentSharpness; }

}

// Function

public void Write()

{

foreach (char c in m_message)

{

if (m_Sharpened == false)

{

if (IsSharp)

{

HttpContext.Current.Response.Write(c);

}

else

{

HttpContext.Current.Response.Write("#");

}

}

else

{

HttpContext.Current.Response.Write(c);

}

m_charsUsed++;

}

HttpContext.Current.Response.Write("<BR>");

}

// Function

public void OnSharpened()

{

m_Sharpened = true;

m_message = "The Mechanical Pencil is self sharpening.";

Write();

}

public void Sharpen(IPencil pencil)

{

}

}

}
 
M

Marina Levit [MVP]

Interfaces are meant for classes that have the same behavior, but different
implementation for that behavior.

For example, a Person object might implement a Move method one way - by
walking.

A Car object might implement a Move method another way - by driving.

However, a Person and a Car, have nothing else in common. They can't share a
common ancestor.

But they can both implement the same interface. And someone with a
collection of objects implementing this interface, can call the Move method
on each of them, without regard as to whether the object is a Car, a Person,
or something else. Because they all implement the same interface, they can
all be moved.

An interface is not a blueprint for a class. If you have only one class
implementing the interface, then you shouldn't have an interface. And if
you have multiple classes implement the interface, but they all have the
same implementation, then you should be using inheritence.
 
D

DeveloperX

Interfaces also allow you to group areas of functionality which makes
developing simpler.
For example imagine a wheel object representing a wheel with a tyre on
it. You might expect to see methods and properties like , width,
height, tread pattern, spoke style, valve, inflate, polish, deflate,
tyremake, hubmake, tyremanufacturer, hubmanufacturer.

Now when you're programming against that wheel you're going to see a
huge list of properties and it might not be immediately clear what they
do.
Now have a wheel object that implements IHub and ITyre things become
clearer. you know IHub.polish will polish the hub, previously you might
have inadvertantly polished the tyre. You can also now remove
tyremanufacturer and hubmanufacturer and simply have manufacturer on
each of the interfaces.
 
R

RSH

Am I correct in that they provide no real direct functionality themselves?
Instead they simply provide a way to ensure that instantiating objects
comply a predetermined set of rules. ...And provide a mechanism for future
development against the class that enlightens the developers on the class's
mandatory properties, and functions?
 
D

DeveloperX

RSH said:
Am I correct in that they provide no real direct functionality themselves?
Instead they simply provide a way to ensure that instantiating objects
comply a predetermined set of rules. ...And provide a mechanism for future
development against the class that enlightens the developers on the class's
mandatory properties, and functions?

Yeah, you hear alot of people describe them as contracts. You know if
it implements an interface it supports what ever functionality is
provided by the interface.
 
S

Simon Tamman

Yup.
They're a real boon in things like distributed applications where the server
knows of the interface but has no way of knowing the concrete type
definitions.
They're ESPECIALLY useful for testing, so to test your classes you send them
a "mock" object that implements the interface being used, but rather then
doing anything useful it just records how the interface is being used so you
can make sure it's being used correctly.

The problem with the example you provided is that your interface was
IPencil, then you ended up trying to force a Pen into being a pencil and a
mechanised pencil into being a pencil.
It should have been IWritingImplement or something like that. OnSharpen
should not have existed, you should have tried mebbe a different interface
like IBreakable with
bool IsBroken and
void Fix(IServiceProvider services);

You could then "fix" the pencil by sharpening it, the pen by... buying a new
pen and the mechanical one by getting an engineer from the services and
making him fix it.
That would probably given you better abstraction and have made more sense.
Also the type property is not necessary. All objects have GetType().Name on
them already.

HTH

Simon Tamman
 
P

PS

RSH said:
Hi,

I have been reading on interfaces working on samples I've run across on
the web. For the life of me I cannot seem to grasp them.

It appears to me that interfaces are simply blueprints to a class, that
when implemented, they require the implementing calss to make sure that
each of the properties, functions etc. are handled by the class. (????)

What I am really having a problem with is how they overcome the limitation
of multiple inheritance? It would appear that interfaces simply require
that a class handles a predetermined number of properties events etc. So
if I have a class that implements an interface and I need to add
functionality to that class...I still have to add it to the interface and
handle it in the initial class...this seems redundant to me. Not to
mention modifying the interface to include the new required functionality,
now makes all other classes that implement the interface "break" and now
require that I modify all classes that implement the interface to handle
the newly added functionality.

Now I openly admit I am no OOP guru, and I am simply trying to understand
interfaces...I am certainly not bashing them.

The code below illustrates my initial attempt at understanding
interfaces...pieced together from a few tutorials on the web.

First I would not think a Pen is a Pencil so your interface might be better
as IWritingInstrument.

IWritingInstrument pencil = new Pencil();
IWritingInstrument mp = new MechanicalPencil();
IWritingInstrument pen = new Pen();

sharpenWritingInstrument(pencil);
sharpenWritingInstrument(mp);
sharpenWritingInstrument(pen);

private void sharpenWritingInstrument(IWritingInstrument wi)
{
if(wi.IsBlunt)
wi.Sharpen();
}

PS
 
M

Mark Wilden

Now have a wheel object that implements IHub and ITyre things become
clearer.

I think this would not be a good idea, because a wheel is not a hub nor is
it a tire. A wheel is composed of these things, so a wheel has a hub and a
tire.

///ark
 
D

Dave Sexton

Hi Ron,

It appears to me that interfaces are simply blueprints to a class, that when
implemented, they require the implementing calss to make sure that each of
the properties, functions etc. are handled by the class. (????)

You can implement an interface and leave all of the members empty, or throw
NotSupportExceptions, or whatever you want. They can't enforce that the
members are handled in any certain way. Instead interfaces define a public
contract that an implementing class must provide to its consumers; enforced by
compilers [and the CLR?].

You can do whatever you want in the interface so long as it doesn't break the
public contract, though certain interfaces do imply constraints on how the
interface should be implemented. i.e., An interface's public behavior. One
such example is the following:

interface IDoThings
{
bool CanDoSomethingFoo { get; }
bool CanDoSomethingBar { get; }

void DoSomethingFoo();
void DoSomethingBar()
}

It will be obvious to callers that CanDoSomethingFoo could be verified as true
before attempting to call DoSomethingFoo. Therefore, implementations must
make sure that CanDoSomethingFoo returns whether DoSomethingFoo can be called.
In this respect interfaces aren't "simply blueprints", but instead also imply
behavioral aspects of all their implementations.

(In .NET, you can define explicit interface implementations so that the
contract exists on the implementing class but it can only be used if the
consumer explicitly casts an instance of the class to the Type of the
explicitly-implemented interface. In other words, you can hide an
implementation of an interface, although consumers can still cast the class to
the interface if desired.)
What I am really having a problem with is how they overcome the limitation
of multiple inheritance?

(I think whether multiple inheritance is a "limitation" is up for debate.)

Regardless, interfaces can't overcome this "limitation" because they don't
provide implementation. Interfaces only provide a public contract. As a
developer you can use the public contracts provided by multiple interfaces on
your class, but you'll still have to code each implementation. In other
words, your class is not actually inheriting the functionality from another
class by implementing an interface. However, you can define multiple
interfaces and implement them on multiple classes so that all of the classes
share the same interface Types, which can't be done using inheritance, but
you'll still have to code each implementation yourself so all that you'd
really gain is shared public contracts spanning multiple concrete
implementations that you had to code anyway.
It would appear that interfaces simply require that a class handles a
predetermined number of properties events etc.

..NET doesn't require that interface members are handled, just that the public
members exist, even if only explicitly.
So if I have a class that implements an interface and I need to add
functionality to that class...I still have to add it to the interface and
handle it in the initial class...this seems redundant to me.

You don't have to do anything ;)

If you are using an interface for any of the reasons found in this thread, or
the many other reasons that haven't been mentioned, then you'll know whether
you have to add new members to the declaration of your interfaces or just the
classes that implement them. As Marina pointed out, you really don't need the
interface if you are only implementing it on one class (and you have no
intention of it being used externally), therefore it will be clear if you are
using an interface and implementing it on multiple classes, whether each class
requires the new member or only one of the particular implementations requires
the new member.

If each implementing class requires the new member, and the interface should
logically contain that member, then add the member to the interface, otherwise
define a new interface or just add the member to the requiring classes. This
is a simplistic rule that doesn't make sense in every circumstance, but is a
good starting point. Other things to consider are versioning requirements,
whether modifying the interface is worth breaking the contract, and whether an
interface is even useful for the new members at all.
Not to mention modifying the interface to include the new required
functionality, now makes all other classes that implement the interface
"break" and now require that I modify all classes that implement the
interface to handle the newly added functionality.

That's why you shouldn't add the new member unless it can be used by all of
the implementing classes. (Or more commonly, unless it can be used by most of
the implementing classes). Remember that you can always define another
interface instead for new members if only a subset of the classes implementing
the current interface can use the new members. Each class in the subset can
implement both interfaces, which is one great advantage of interfaces over
inheritance.

<snip>
 
R

RSH

Thanks all!

This is some really goosd stuff...and thank you Dave for that incredibly
clear explanation!!!!

Dare I post my updated code. I modified it based on my new interpretation
of interfaces.
Any comments or feedback would be greatly appreciated. I'm pretty new at
this stuff :)

THANKS!

Ron



public partial class _Default : System.Web.UI.Page

{

protected void Page_Load(object sender, EventArgs e)

{

IWritingInstrument pencil = new Pencil();

pencil.Write();

pencil.IsWritingPoorly = true;

pencil.IsBroken = true;

IWritingInstrument mpencil = new MechanicalPencil();

mpencil.Write();

mpencil.IsWritingPoorly = true;

mpencil.IsBroken = true;

IWritingInstrument pen = new Pen();

pen.Write();

pen.IsWritingPoorly = true;

pen.IsBroken = true;

}



// Interfaces +++++++++++++++++++++++++++++++++

//Writing Implement Interface

public interface IRepair

{

bool IsWritingPoorly { get; set; }

void Write();

void Fix();

}

//Is Breakable Interface

public interface IReplace

{

bool IsBroken { get; set; }

void Replace();

}

//Combine Interfaces

public interface IWritingInstrument : IRepair, IReplace

{

}



// Classes +++++++++++++++++++++++++++++++++++++

// Pencil Class

public class Pencil : IWritingInstrument

{

private string m_message;

private Boolean m_isWritingPoorly;

private Boolean m_isBroken;

// Constructor

public Pencil()

{

m_isWritingPoorly = false;

m_isBroken = false;

m_message = "";

}

// Property

public Boolean IsBroken

{

get { return m_isBroken; }

set

{

m_message = "The " + this.GetType().Name + " appears to be Broken...we will
replace it for you...";

Write();

Replace();

m_isBroken = false;

}

}

// Property

public bool IsWritingPoorly

{

get { return m_isWritingPoorly; }

set

{

m_message = "The " + this.GetType().Name + " appears to be Dull...we will
sharpen it for you...";

Write();

Fix();

m_isWritingPoorly = false;

}

}

// Function

public void Write()

{

HttpContext.Current.Response.Write(m_message + "<BR>");

}

// Function

public void Fix()

{

m_message = "The " + this.GetType().Name + " was sharpened and is now
working great!<br>";

Write();

}

public void Replace()

{

m_message = "The " + this.GetType().Name + " was replaced.<br>";

Write();

}

}

// Pen Class

public class Pen : IWritingInstrument

{

private string m_message;

private Boolean m_isWritingPoorly;

private Boolean m_isBroken;

// Constructor

public Pen()

{

m_isWritingPoorly = false;

m_isBroken = false;

m_message = "";

}

// Property

public Boolean IsBroken

{

get { return m_isBroken; }

set

{

m_message = "The " + this.GetType().Name + " appears to be Broken...we will
replace it for you...";

Write();

Replace();

m_isBroken = false;

}

}

// Property

public bool IsWritingPoorly

{

get { return m_isWritingPoorly; }

set

{

m_message = "The " + this.GetType().Name + " appears to be out of ink...we
will refill it for you...";

Write();

Fix();

m_isWritingPoorly = false;

}

}

// Function

public void Write()

{

HttpContext.Current.Response.Write(m_message + "<BR>");

}

// Function

public void Fix()

{

m_message = "The " + this.GetType().Name + " was refilled and is now working
great!<br>";

Write();

}

public void Replace()

{

m_message = "The " + this.GetType().Name + " was replaced.<br>";

Write();

}

}



// MechanicalPencil Class

public class MechanicalPencil : IWritingInstrument

{

private string m_message;

private Boolean m_isWritingPoorly;

private Boolean m_isBroken;

// Constructor

public MechanicalPencil()

{

m_isWritingPoorly = false;

m_isBroken = false;

m_message = "";

}

// Property

public Boolean IsBroken

{

get { return m_isBroken; }

set

{

m_message = "The " + this.GetType().Name + " appears to be Broken...we will
replace it for you...";

Write();

Replace();

m_isBroken = false;

}

}

// Property

public bool IsWritingPoorly

{

get { return m_isWritingPoorly; }

set

{

m_message = "The " + this.GetType().Name + " appears to be out of lead...we
will replace the lead for you...";

Write();

Fix();

m_isWritingPoorly = false;

}

}

// Function

public void Write()

{

HttpContext.Current.Response.Write(m_message + "<BR>");

}

// Function

public void Fix()

{

m_message = "The " + this.GetType().Name + "'s lead was replaced and is now
working great!<br>";

Write();

}

public void Replace()

{

m_message = "The " + this.GetType().Name + " was replaced.<br>";

Write();

}

}

}
 
G

Guest

I think you get it. The example I like to use when explaining using
interfaces is the media player

public interface IMediaPlayer
{
FastForward();
Rewind()
Play();
Stop();
}

Then you can declare classes like

MP3Player : IMediaPlayer
VideoPlayer : IMediaPlayer

Each class performs the same functions, but would be implemented very
differently. You can have common code that does something like:

IMediaPlayer mp;
string playerType = "mp3"
mp = new MP3Player();
mp.Play();
mp.Stop();

mp = new VideoPlayer();
mp.Play();
mp.Stop();

Imagine interfaces being useful if you were writing a Media player that
plays audio files, video files, DVDs, etc.

Each has the same function, but are implemented differently.
 
G

Guest

Sorry, I meant to write the code like this:

IMediaPlayer mp;
string playerType = "mp3"

switch(playerType)
{
case "mp3" : mp = new MP3Player(); break;
case "video" : mp = new VideoPlayer(); break;
}

mp.Play();
mp.Stop();
 
R

RSH

One last question...


I have two interfaces that I combine into a new one
public interface IRepair

{

bool IsWritingPoorly { get; set; }

void Write();

void Fix();

}

//Replace Interface

public interface IReplace

{

bool IsBroken { get; set; }

void Replace();

}



//Combine Interfaces

public interface IWritingInstrument : IRepair, IReplace

{

}



Now I need to add a new interface for refilling the pen. But the pencil and
Mechanical Pencil objects don't need the refill interface. So my class
declarations look like this:

public class Pencil : IWritingInstrument

{

.... the code goes here

}



public class MechanicalPencil : IWritingInstrument

{

.... the code goes here

}



But now I need to add an interface specifically for ink WritingInstruments
so I add an interface:

//Refill Interface

public interface IRefill

{

bool NeedsRefilling { get; set; }

void Refill();

}

....and my class delaration looks like this:

public class Pen : IWritingInstrument, IRefill

{

....code goes here

}



Now for my question...

In the examples so far the objects are instantiated like this:

IWritingInstrument pencil = new Pencil();



IWritingInstrument mpencil = new MechanicalPencil();



The problem is that I need the IWriting Instrument Interface, but in
addition I need the IRefill interface just for them pen, not the pencils.
In which case is it correct to create the object as follows?

I don't want the pencils to have a refill function, it doesn't make any
sense.



Pen pen = new Pen();

Basic testing shows that the interfaces still seem to require each member of
the "contract" so everything appears to be working correctly...so am I to
assume this is okay to do?



Thanks!

Ron
 
D

Dave Sexton

Hi Ron,

I recommend against using interfaces unless they will add some value. In your
examples, you haven't provided any requirements that lead me to believe
interfaces will be useful to you at all. For that reason it's hard to tell
you what you should and shouldn't do in your code. From the limited
requirements you've stated thus far, I'd recommend not using interfaces at
all.

If you are going to pass the pen that you defined in your example to a method
and if at some point in code you may pass a different implementation of
IWritingInstrument to the same method then an interface could be useful. If
not, then you probably don't need to use interfaces. Other uses for
interfaces are in COM interop and certain design patterns.

The interfaces and members you have chosen don't make much sense though. For
instance, the Write method should be on the IWritingInstrument interface, not
IRepair, because even instruments that can't break may need to Write something
:). And there is no reason for the IRepair and IReplace interfaces since they
must be implemented by all IWritingInstrument implementations anyway and you
haven't shown any external requirement for them. I think the following
solution makes more sense, considering that the interfaces you have defined
aren't based on any business requirements of which I'm unaware. My examples
afterwards use the interfaces, thus rationalizing their existence in the first
place.

interface IRefillable
{
bool ShouldRefill { get; set; }
bool CanRefill { get; }
void Refill();
}

interface IWritingInstrument
{
// replacement
bool ShouldReplace { get; }
bool CanReplace { get; }
void Replace();

// repair
bool IsWritingPoorly { get; set; }
bool IsBroken { get; set; }
bool CanRepair { get; }
void Repair();

// use
void Write(string words);
}

class Pen : IWritingInstrument, IRefillable
{
private bool broken;
public bool IsBroken { get { return broken; } set { broken = value; } }

public void Write(string words)
{
if (broken)
// don't try to write with a broken utensil!
throw new BrokenWritingInstrumentException(this); // undeclared
in my example

Console.WriteLine("Pen: " + words);

// crappy pen ;)
broken = true;
}
...
}

class Pencil : IWritingInstrument
{
public void Write(string words)
{
Console.WriteLine("Pencil: " + words);

// note that Pencil's don't break after writing, unlike Pens
}
...
}
....

The problem is that I need the IWriting Instrument Interface, but in
addition I need the IRefill interface just for them pen, not the pencils. In
which case is it correct to create the object as follows?
I don't want the pencils to have a refill function, it doesn't make any
sense.
Pen pen = new Pen();

I understand that you are using Pen pen = new Pen() because you want access to
your IRefill interface, but you could just as easily do the following:

IRefillable refillableUtensil = new Pen();

Now, with refillableUtensil, you can pass it to any method that accepts a
parameter of Type IRefillable. If you don't have any such methods defined (or
any use for IRefillable) then you don't need the interface. For instance, if
Pen is the only object that is IRefillable and you don't have any particular
reason to code against the IRefillable interface instead of the Pen class
itself, then just declare the Refill method in the Pen class and don't even
declare the interface.

Use the IWritingInstrument interface if code such as the following is desired:

void Test()
{
Pen pen = new Pen();

if (!TestWritingInstrument(pen))
Console.WriteLine("1: Pen is broken");
else
Console.WriteLine("1: Pen works just fine");

if (!TestWritingInstrument(pen))
Console.WriteLine("2: Pen is broken");
else
Console.WriteLine("2: Pen works just fine");

if (!TestWritingInstrument(new Pencil()))
Console.WriteLine("Pencil is broken");
else
Console.WriteLine("Pencil works just fine");
}

// This method doesn't know whether it's testing a Pen or a Pencil,
// which is the reason for the interface in the first place
bool TestWritingInstrument(IWritingInstrument utensil)
{
if (utensil == null)
throw new ArgumentNullException("utensil");

if (utensil.IsBroken)
// test failed!
return false;

// if IsBroken wasn't defined we could just call Write and catch
// BrokenWritingInstrumentException and then return false

utensil.Write("This is a test!");

// assume test passed
return true;
}


For the sake of using IRefillable in an example, you could have a method such
as the following:

void Write(IWritingInstrument utensil, string words)
{
if (utensil == null)
throw new ArgumentNullException("utensil");

if (utensil.ShouldReplace)
utensil.Replace();

IRefillable refillable = utensil as IRefillable;

if (refillable != null && refillable.ShouldRefill)
{
if (refillable.CanRefill)
refillable.Refill();
else if (utensil.CanReplace)
utensil.Replace();
else
throw new InvalidOperationException("The writing instrument is
empty and cannot be refilled or replaced at this time.");
}

// this method may throw BrokenWritingInstrumentException,
// which is not defined in my example
utensil.Write(words);
}


With the above method defined you can write with any IWritingInstrument and be
sure not to run out of "juice":

Write(new Pen(), "Test custom Write method");
Write(new Pencil(), "Test custom Write method");


(Please note that I haven't tested this code so it will probably require
modifications to build correctly)
 
R

RSH

Oh Dave I have way too much to learn...thank you for your assistance. Just
when i thought I was beginning to understand interfaces :)

Thank you for your time!
Ron
 
M

Mark Wilden

Dave Sexton said:
I recommend against using interfaces unless they will add some value. In
your examples, you haven't provided any requirements that lead me to
believe interfaces will be useful to you at all. For that reason it's
hard to tell you what you should and shouldn't do in your code. From the
limited requirements you've stated thus far, I'd recommend not using
interfaces at all.

In another thread, you were looking for some agreement between us. Consider
it found. :)

///ark
 
D

Dave Sexton

Hi Mark,

I'm glad to hear that you agree with me on the point I made about the OP's use
of interfaces :)

But in our conversation I wasn't looking for agreement just for the sake of
agreeing, but instead for the sake of learning. When a conversation ends
without agreement, everyone's left with one or more competing ideas and no
solution, although I think we located the root of our difference of opinion
anyway.
 
L

Laurent Bugnion

Hi,

Dave said:
Hi Mark,

I'm glad to hear that you agree with me on the point I made about the OP's use
of interfaces :)

But in our conversation I wasn't looking for agreement just for the sake of
agreeing, but instead for the sake of learning. When a conversation ends
without agreement, everyone's left with one or more competing ideas and no
solution, although I think we located the root of our difference of opinion
anyway.

I think there can be learning without agreement (unless I misunderstand
what agreement really means in english). I still don't really agree with
Mark's thoughts about documenting the source code, but I have thought *a
lot* about it since we talked about that, and I think it will help me to
be more efficient about my coding.

HTH,
Laurent
 
D

Dave Sexton

Hi Laurent,

I didn't mean to imply that our conversation was pointless. I believe it was
helpful to me as well. I was trying to come to an agreement with Mark for the
sake of learning so we could validate or disproove our beliefs and have a
better understanding of what is the "right way of doing things". We never
came to such an agreement because we disagreed on other things that were
off-topic, as I pointed out.

I only replied with that statement because it seemed that Mark's comments were
meant to say, "here's your agreement, Dave". That's not what I wanted when I
asked to agree on something - just any agreement on anything, even something
completely unrelated such as the use of interfaces :)
 

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