Interface and enums

B

Bob

Hi,
Can someone explain why you can't declare enums in an interface?
The compiler says "interfaces can't declare types"
Ignoring the syntax implications it seems to me that you should be able to
declare that an enum exists. i.e. It is within the 'spirit' of an interface
to state that it exists. The implementing class will provide the members.

e.g. I have a code library that performs a function.
It exposes two interfaces which allow for two different ways of asking for
the function.
One way involves a public enum, i.e. Some of the method calls accept the
enum as a parameter, the other does not.
It seems to me that I should be able to declare the enum in one interface
and leave it out of the other.
Currently the enum is available to declared objects of either interface.
e.g.
ImyFirstInterface FirstInterface = new MyLib.myImplementingclass();
ImySecondInterface SecondInterface = new MyLib.myImplementingclass();

Both FirstInterface and SecondInterface can see MyLib.myPublicEnum
thanks
Bob
 
M

Mattias Sjögren

Ignoring the syntax implications it seems to me that you should be able to
declare that an enum exists. i.e. It is within the 'spirit' of an interface
to state that it exists. The implementing class will provide the members.

How would your client code consume the enum if you don't know its
members?


Mattias
 
B

Bob

Hi Mattias,
I see it happening in much the same way as any other interface
implementation.
i.e.

****Interface code *****
public Interface IMyInterface
{
enum MyJamChoice{};
bool JamInStock(MyJamChoice whichone);
}
****End Interface Code

*****Implementation code*****
In MyImplementationClass we have
enum ImyInterface.MyJamChoice
{
Strawberry,
Apricot
}
bool ImyInterface.JamInStock(ImyInterface.MyJamChoice whichone)
{
//Jam checking code return true if in stock
}
**********End of Implementation code *******

****Client Code***
ImyInterface = new MyImplementationClass()
//at this point Intellisense knows the enum contents
if (ImyInterface.JamInStock(ImyInterface.MyJamChoice.StrawBerry )
{//Lets have breakfast}
**** End of Client code****
regards
Bob
 
M

Mattias Sjögren

****Client Code***
ImyInterface = new MyImplementationClass()

Should I assume that ImyInterface is a variable of type IMyInterface
or what?
//at this point Intellisense knows the enum contents
if (ImyInterface.JamInStock(ImyInterface.MyJamChoice.StrawBerry )

It does? If ImyInterface is indeed a variable of type IMyInterface,
the compiler knows nothing about the concrete implementation
(MyImplementationClass) you're using. That's kind of the point of
using interfaces - to be able to write the same code regardless of
implementation.


Mattias
 
?

=?ISO-8859-2?Q?Marcin_Grz=EAbski?=

Hi Bob,

Bob napisa³(a):
Hi Mattias,
I see it happening in much the same way as any other interface
implementation.
i.e.

****Interface code *****
public Interface IMyInterface
{
enum MyJamChoice{};
bool JamInStock(MyJamChoice whichone);
}
****End Interface Code

*****Implementation code*****
In MyImplementationClass we have
enum ImyInterface.MyJamChoice
{
Strawberry,
Apricot
}
bool ImyInterface.JamInStock(ImyInterface.MyJamChoice whichone)
{
//Jam checking code return true if in stock
}
**********End of Implementation code *******

You can not just define the interface of (any) type!
Interface is the contract wich gives all needed functionality.
If you declare the empty interface then the only thing
you can provide is the "empty" implementation of it.
The value types can implement interfaces but the enums can not,
because they have only values as a members.

It is important that if you want to provide the interface
with enums (as a arguments), you'll have to define these
enums, because you need to define the contract.

With regards
Marcin
 
B

bob

Hi Marcin and Mattias,
I know that I can't do this.
This is more a philisophical discussion on why not.
I see nothing wrong with defining an empty enum in the interface and
providing the members in the implementation.
I have yet to be convinced that it should not be achievable.
my pseudo code was meant to convey this.
Harking back to my Jam stocktake.
What is wrong with the concept?
I would implement the interface and fill the enum with Strawberry and
apricot.
You could implement the interface and fill the enum with
Plum and blackberry.
My client code could choose one of my jams
Your client code could choose one of your jams.
regards
Bob
 
P

PS

Bob said:
Hi Mattias,
I see it happening in much the same way as any other interface
implementation.
i.e.

****Interface code *****
public Interface IMyInterface
{
enum MyJamChoice{};
bool JamInStock(MyJamChoice whichone);
}
****End Interface Code

*****Implementation code*****
In MyImplementationClass we have
enum ImyInterface.MyJamChoice
{
Strawberry,
Apricot
}
bool ImyInterface.JamInStock(ImyInterface.MyJamChoice whichone)
{
//Jam checking code return true if in stock
}
**********End of Implementation code *******

****Client Code***
ImyInterface = new MyImplementationClass()
//at this point Intellisense knows the enum contents
if (ImyInterface.JamInStock(ImyInterface.MyJamChoice.StrawBerry )
{//Lets have breakfast}
**** End of Client code****

Enums are not "dynamic" like that.

Here is an example to see if this is the problem you are trying to avoid.

interface ICarFactory
{
Car MakeCar(ModelsEnum model);
}

ICarFactory factory = new FordFactory();
factory.MakeCar(ModelsEnum.ToyotaRav4);

PS
regards
Bob
 
C

Chris Dunaway

Hi Marcin and Mattias,
I know that I can't do this.
This is more a philisophical discussion on why not.
I see nothing wrong with defining an empty enum in the interface and
providing the members in the implementation.

What it two classes that implement your interface have two different
implementations for the enum? What if they then need to communicate
the enum variable to a third class? How is the third class to know
which implementation of the enum to use? What if they conflict?
 
B

bob

Hi,
Your example is much more succint than mine.
Excellent.
In my brave new world your ICarFactory interface would also declare
ModelEnum{}
Your FordFactory implemenation would be forced to fill it. Hopefully with
'starlet','escort' etc

In the client code
Once the ; is typed in
ICarFactory factory = new FordFactory();
Intellisense knows the contents of ModelEnum from its inspection of the
FordFactory implementation
When you type in
factory.MakeCar(ModelsEnum.
You are presented with the contents of Fordfactory.ModelsEnum
Rav4 would not be in the list and would force a type checking error if you
insisted on typing it in.
regards
Bob
Enums are not "dynamic" like that.

Here is an example to see if this is the problem you are trying to avoid.

interface ICarFactory
{
Car MakeCar(ModelsEnum model);
}

ICarFactory factory = new FordFactory();
factory.MakeCar(ModelsEnum.ToyotaRav4);

PS
 
B

bob

Hi Chris,
Please see my reply to PS. His example is much better than mine.
There can be no confusion because at some point you must instantiate your
interface declaration in the client code. Once you type in
IMyInterface m = new SomeImplementation();
You have locked down the enum to what ever is in the SomeImplementation.
regards
Bob
 
M

Mattias Sjögren

In the client code
Once the ; is typed in
ICarFactory factory = new FordFactory();
Intellisense knows the contents of ModelEnum from its inspection of the
FordFactory implementation

No it doesn't. IntelliSense looks at the type of the variable. It
doesn't know about the actual implementing type used at runtime. Your
example is too simplistic. When using interfaces, it's very common to
not know the actual type that will be used.

Take a look at this for example

void Foo(bool preferAmericanCars)
{
ICarFactory factory;
if (preferAmericanCar)
factory = new FordFactory();
else
factory = new ToyotaFactory();

factory.MakeCar(...

At this point, which "implementation" of the enum would you use? And
how would IntelliSense and the compiler know?


Mattias
 
B

Bob

Hi Mattias,
Yep,
that is a weakness with my idea given the current semantics.

I guess what I am proposing here would need to be some sort of 'Sealed
Interface'
i.e. You can only declare say a 'IFordFactory' or a 'IToyotaFactory'

My real world situation that led to this line of reasoning is:
AppA has an internal widgetprocessing class
AppB also processes widgets but does it using a DLL because it is
fundamentally different to AppA
Along comes a third party SuperWidgetProcessor class library that I want to
bolt on to AppA and also make available to AppB users who may or may not
decide to take it on board.

So I wrap SuperWidgetProcessor and expose its functionality through two
interfaces say IA and IB.
Easiest way to insert into AppA is to have the AppA WidgetProcessing class
declare a private IA and route all its functionality to it. This way all
changes are confined to the WidgetProcessing class.

Trouble is that the other classes tell the WidgetProcessing class what they
want by passing in a request class that has Properties based on enums. So my
wrapper exposes a set of identically named enums and the routing code is
readable.
AppB uses a completely different approach so the enum thing is not needed.

So..
I am left with a wrapper that has a public enum that is useful to only one
out of two interfaces.
Hence my current line of reasoning of wanting to expose the enum only
through IA.

Ah well,
Perhaps in another life.
Thank you all for your thoughts.
regards
Bob
 
P

PS

Bob said:
Hi Mattias,
Yep,
that is a weakness with my idea given the current semantics.

I guess what I am proposing here would need to be some sort of 'Sealed
Interface'
i.e. You can only declare say a 'IFordFactory' or a 'IToyotaFactory'

My real world situation that led to this line of reasoning is:
AppA has an internal widgetprocessing class
AppB also processes widgets but does it using a DLL because it is
fundamentally different to AppA
Along comes a third party SuperWidgetProcessor class library that I want
to
bolt on to AppA and also make available to AppB users who may or may not
decide to take it on board.

So I wrap SuperWidgetProcessor and expose its functionality through two
interfaces say IA and IB.
Easiest way to insert into AppA is to have the AppA WidgetProcessing class
declare a private IA and route all its functionality to it. This way all
changes are confined to the WidgetProcessing class.

Trouble is that the other classes tell the WidgetProcessing class what
they
want by passing in a request class that has Properties based on enums. So
my
wrapper exposes a set of identically named enums and the routing code is
readable.
AppB uses a completely different approach so the enum thing is not needed.

So..
I am left with a wrapper that has a public enum that is useful to only one
out of two interfaces.
Hence my current line of reasoning of wanting to expose the enum only
through IA.

I did get a little lost in your explanation. But if you want to keep "type
safety" with your enums then you can cast between different enums by
converting them to integers temporarily.

For example

enum CarModel
{
FordEscort = 1,
FordEscape = 2,
ToyotaRav4 = 3
}

enum FordModel
{
FordEscort = 1,
FordEscape = 2
}

enum ToyotaModel
{
ToyotaRav4 = 3
}

This way the FordFactory takes FordModel, the ToyotaFactory takes
ToyotaModel and your wrapper / abstract factory takes CarModel. The wrapper
/ abstract factory does need to do validate the values but after they are
validated they are converted like (ToyotaModel)(int)CarModel.ToyotaRav4.

Maybe this will help?

PS
 
B

bob

Hi PS,
I think my problem is that I didn't look at the big picture properly.
I got locked into trying to hide the enum from InterfaceB consumers. But
when I look downstream clearly the InterfaceB offering will be presented to
the consumers as a new version of their existng DLL so they won't see any of
the InterfaceA baggage anyway.
regards
Bob

Bob said:
Hi Mattias,
Yep,
that is a weakness with my idea given the current semantics.

I guess what I am proposing here would need to be some sort of 'Sealed
Interface'
i.e. You can only declare say a 'IFordFactory' or a 'IToyotaFactory'

My real world situation that led to this line of reasoning is:
AppA has an internal widgetprocessing class
AppB also processes widgets but does it using a DLL because it is
fundamentally different to AppA
Along comes a third party SuperWidgetProcessor class library that I want
to
bolt on to AppA and also make available to AppB users who may or may not
decide to take it on board.

So I wrap SuperWidgetProcessor and expose its functionality through two
interfaces say IA and IB.
Easiest way to insert into AppA is to have the AppA WidgetProcessing class
declare a private IA and route all its functionality to it. This way all
changes are confined to the WidgetProcessing class.

Trouble is that the other classes tell the WidgetProcessing class what
they
want by passing in a request class that has Properties based on enums. So
my
wrapper exposes a set of identically named enums and the routing code is
readable.
AppB uses a completely different approach so the enum thing is not needed.

So..
I am left with a wrapper that has a public enum that is useful to only one
out of two interfaces.
Hence my current line of reasoning of wanting to expose the enum only
through IA.

I did get a little lost in your explanation. But if you want to keep "type
safety" with your enums then you can cast between different enums by
converting them to integers temporarily.

For example

enum CarModel
{
FordEscort = 1,
FordEscape = 2,
ToyotaRav4 = 3
}

enum FordModel
{
FordEscort = 1,
FordEscape = 2
}

enum ToyotaModel
{
ToyotaRav4 = 3
}

This way the FordFactory takes FordModel, the ToyotaFactory takes
ToyotaModel and your wrapper / abstract factory takes CarModel. The wrapper
/ abstract factory does need to do validate the values but after they are
validated they are converted like (ToyotaModel)(int)CarModel.ToyotaRav4.

Maybe this will help?

PS
 

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