Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Java > enum and switch

Reply
Thread Tools

enum and switch

 
 
Daniel Pitts
Guest
Posts: n/a
 
      03-08-2007
On Mar 7, 11:11 am, Wojtek <(E-Mail Removed)> wrote:
> Daniel Pitts wrote :
>
>
>
> > On Mar 7, 10:06 am, "Daniel Dyer" <"You don't need it"> wrote:
> >> On Wed, 07 Mar 2007 17:36:49 -0000, Wojtek <(E-Mail Removed)> wrote:
> >>>>> Is there a way to use an enum in a switch statement?
> >>>> You don't need to qualify the enum constants. In fact, you are only
> >>>> allowed to use unqualified names. So it should be:
> >>>> switch (thing)
> >>>> {
> >>>> case ONE:
> >>>> // Do something.
> >>>> case TWO:
> >>>> // Do something else.
> >>>> }

>
> >>>> Dan.

>
> >>> OK, but what if the enum is from another class? I must then qualify it.
> >>> BTW I ended up using an if/else if tree, though I would rather use a
> >>> switch/case.

>
> >> Did you try it with the switch statement and the unqualified labels? The
> >> compiler knows what class the enum constants are from because it knows the
> >> type of the argument to the switch statement.

>
> >> Dan.

>
> >> --
> >> Daniel Dyerhttp://www.uncommons.org

>
> > Or, even better... Ever hear of Polymorphism?

>
> > // Look ma! No Switches!
> > public class MyClass {
> > public enum Things {
> > ONE {
> > public boolean doStuff(MyClass myClass) {
> > return myClass.doStuff(1);
> > }
> > },
> > TWO {
> > public boolean doStuff(MyClass myClass) {
> > return myClass.doStuff(2);
> > }
> > }
> > ;
> > public abstract boolean doStuff(MyClass myClass);

>
> > }

>
> > public boolean process(Things thing) {
> > return thing.doStuff(this);
> > }

>
> > private boolean doStuff(int i) {
> > return false;
> > }
> > }

>
> Well, ok, except that there is more happening in each case than a
> method call. And I need to take the time to sit down and actually READ
> about Java 1.5+
>
> Sigh, not enough hours in each day, and those damn deadlines.....
>
> --
> Wojtek


The point is to move the change in behavior out of the switch
statement and into the object you are switching on.

public enum Things {
ONE {
public boolean doStuff(MyClass myClass) {
// Do lots of stuff to myClass
//...
}
},
TWO {
public boolean doStuff(MyClass myClass) {
// Do lots of stuff other stuff to myClass
//...
}
}
;
public abstract boolean doStuff(MyClass myClass);
}

This is called the State/Strategy pattern. You'll find that well
designed OO programs tend NOT to have switch statements. Especially
switch statements which switch on the same object in more than one
location. Just put a method on the object, and override it for the
different cases.

 
Reply With Quote
 
 
 
 
John W. Kennedy
Guest
Posts: n/a
 
      03-08-2007
Wojtek wrote:
> Daniel Dyer wrote :
>>
>> The compiler knows what class the enum constants are from because it
>> knows the type of the argument to the switch statement.

>
> Argh, inconsistencies drive me nuts...
>
> So the compiler knows about the enum constants from the switch, but If I
> have:
>
> if ( thing == ONE )
>
> That fails because I have not qualified the enum constant.


In every ""switch(Enum), each "case" /must/ be a value of Enum. An "if",
on the other hand, can be any expression that eventually boils down to a
boolean.

--
John W. Kennedy
"The blind rulers of Logres
Nourished the land on a fallacy of rational virtue."
-- Charles Williams. "Taliessin through Logres: Prelude"
 
Reply With Quote
 
 
 
 
Patricia Shanahan
Guest
Posts: n/a
 
      03-08-2007
John W. Kennedy wrote:
> Wojtek wrote:
>> Daniel Dyer wrote :
>>>
>>> The compiler knows what class the enum constants are from because it
>>> knows the type of the argument to the switch statement.

>>
>> Argh, inconsistencies drive me nuts...
>>
>> So the compiler knows about the enum constants from the switch, but If
>> I have:
>>
>> if ( thing == ONE )
>>
>> That fails because I have not qualified the enum constant.

>
> In every ""switch(Enum), each "case" /must/ be a value of Enum. An "if",
> on the other hand, can be any expression that eventually boils down to a
> boolean.
>


That still does not explain why qualification is prohibited. It would
appear to be harmless, and in some situations make code more orthogonal,
provided the types match.

Patricia
 
Reply With Quote
 
Daniel Pitts
Guest
Posts: n/a
 
      03-08-2007
On Mar 7, 6:58 pm, Patricia Shanahan <(E-Mail Removed)> wrote:
> John W. Kennedy wrote:
> > Wojtek wrote:
> >> Daniel Dyer wrote :

>
> >>> The compiler knows what class the enum constants are from because it
> >>> knows the type of the argument to the switch statement.

>
> >> Argh, inconsistencies drive me nuts...

>
> >> So the compiler knows about the enum constants from the switch, but If
> >> I have:

>
> >> if ( thing == ONE )

>
> >> That fails because I have not qualified the enum constant.

>
> > In every ""switch(Enum), each "case" /must/ be a value of Enum. An "if",
> > on the other hand, can be any expression that eventually boils down to a
> > boolean.

>
> That still does not explain why qualification is prohibited. It would
> appear to be harmless, and in some situations make code more orthogonal,
> provided the types match.
>
> Patricia

I agree, but what about this case (no pun intended):

public void foo(Thing thing) {
Integer ONE = 1;
switch (thing) {
case ONE: // case branches are never expression.
// so no ambiguity
}
if (thing == ONE) { // Ambiguous.
}
}

I think it has more to do with the fact that there can't ever be
ambiguity for case branches.

 
Reply With Quote
 
Andreas Leitgeb
Guest
Posts: n/a
 
      03-08-2007
On Mar 7, 11:11 am, Wojtek <(E-Mail Removed)> wrote:
> ..., and those damn deadlines.....


So, you don't like the swooshing sound as they pass by ???


Daniel Pitts <(E-Mail Removed)> wrote:
> This is called the State/Strategy pattern. You'll find that well
> designed OO programs tend NOT to have switch statements. Especially
> switch statements which switch on the same object in more than one
> location.


I'd say it mostly depends on how tightly related the switch body
is to the current class/method it is placed in.

Tearing apart logical units of code into separate classes is
also a good recipe for preventing reliably any future attempt
to understand what the code is actually doing.

My suggestion is to have a enum's method return the specific
parameters that allow the switch-arms to be united.
Where this is considered unfeasible, stick to switch.

Don't put any logic into an enum, that is not mainly related
to that enum.

 
Reply With Quote
 
Wojtek
Guest
Posts: n/a
 
      03-08-2007
Daniel Pitts wrote :
> The point is to move the change in behavior out of the switch
> statement and into the object you are switching on.
>
> public enum Things {
> ONE {
> public boolean doStuff(MyClass myClass) {
> // Do lots of stuff to myClass
> //...
> }
> },
> TWO {
> public boolean doStuff(MyClass myClass) {
> // Do lots of stuff other stuff to myClass
> //...
> }
> }
> ;
> public abstract boolean doStuff(MyClass myClass);
> }
>
> This is called the State/Strategy pattern. You'll find that well
> designed OO programs tend NOT to have switch statements. Especially
> switch statements which switch on the same object in more than one
> location. Just put a method on the object, and override it for the
> different cases.


So you are telling me that the enum (which is in another class) must
know about the business logic being evaluated?

The enum I am using is in a class which holds filter criteria. An array
of these filters is passed into a file reader. The file reader reads in
a line, then for each filter in the array evaluates the line. If the
line meets the conditions then it is placed into a collection, to be
written out to a Web page.

The filter array is built up in the business logic class of a use case.
The filter criteria is created by the user via a servlet. There is a
method which iterates through the filters and builds up a human
readable display of the filter criteria. With I18N conversion. To be
displayed at the top of the page which displays the results.

So I have this enum in two switch statements in two different places.
Putting both sets of business logic in the enum seems very wrong to me.
Even with overriding of methods, I would still need to have both method
signatures in the enum. Which means that the enum would still need to
know about what it is being used for. Which breaks use case separation.

And if the enum is in a library, then the library would need to be
modified each time the enum is used in a new place.

After all, an enum is just a way of gathering state criteria in a
convenient package (type). This can then be used as a parameter which
allows the compiler to ensure type safety.

I do not know about other OO languages, but the Java enum definition
which allows methods to be attached to enum elements is completely new
to me.

--
Test Sig


 
Reply With Quote
 
Wojtek
Guest
Posts: n/a
 
      03-08-2007
Wojtek wrote :

> I do not know about other OO languages, but the Java enum definition which
> allows methods to be attached to enum elements is completely new to me.


Ok, I can see having characteristics in the enum element.

In fact I am going to put the language key and a method
getLanguageKey() as part of each element.

But I do not think that behaviour should be there.

--
Test Sig


 
Reply With Quote
 
John W. Kennedy
Guest
Posts: n/a
 
      03-08-2007
Wojtek wrote:
> I do not know about other OO languages, but the Java enum definition
> which allows methods to be attached to enum elements is completely new
> to me.


It was a natural result of Java's everything-is-an-object philosophy.

--
John W. Kennedy
"The blind rulers of Logres
Nourished the land on a fallacy of rational virtue."
-- Charles Williams. "Taliessin through Logres: Prelude"
 
Reply With Quote
 
andrewmcdonagh
Guest
Posts: n/a
 
      03-08-2007
On Mar 8, 2:38 pm, Wojtek <(E-Mail Removed)> wrote:
> Daniel Pitts wrote :
>
>
>
> > The point is to move the change in behavior out of the switch
> > statement and into the object you are switching on.

>
> > public enum Things {
> > ONE {
> > public boolean doStuff(MyClass myClass) {
> > // Do lots of stuff to myClass
> > //...
> > }
> > },
> > TWO {
> > public boolean doStuff(MyClass myClass) {
> > // Do lots of stuff other stuff to myClass
> > //...
> > }
> > }
> > ;
> > public abstract boolean doStuff(MyClass myClass);
> > }

>
> > This is called the State/Strategy pattern. You'll find that well
> > designed OO programs tend NOT to have switch statements. Especially
> > switch statements which switch on the same object in more than one
> > location. Just put a method on the object, and override it for the
> > different cases.

>
> So you are telling me that the enum (which is in another class) must
> know about the business logic being evaluated?
>
> The enum I am using is in a class which holds filter criteria. An array
> of these filters is passed into a file reader. The file reader reads in
> a line, then for each filter in the array evaluates the line. If the
> line meets the conditions then it is placed into a collection, to be
> written out to a Web page.
>
> The filter array is built up in the business logic class of a use case.
> The filter criteria is created by the user via a servlet. There is a
> method which iterates through the filters and builds up a human
> readable display of the filter criteria. With I18N conversion. To be
> displayed at the top of the page which displays the results.
>
> So I have this enum in two switch statements in two different places.
> Putting both sets of business logic in the enum seems very wrong to me.
> Even with overriding of methods, I would still need to have both method
> signatures in the enum. Which means that the enum would still need to
> know about what it is being used for. Which breaks use case separation.
>
> And if the enum is in a library, then the library would need to be
> modified each time the enum is used in a new place.
>
> After all, an enum is just a way of gathering state criteria in a
> convenient package (type). This can then be used as a parameter which
> allows the compiler to ensure type safety.
>
> I do not know about other OO languages, but the Java enum definition
> which allows methods to be attached to enum elements is completely new
> to me.
>
> --
> Test Sig


By using the enum in this way and having code spread throughout your
app which checks which enum is being referenced to decide what to do,
it sounds like your design needs to be 'normalised' in an OO way...as
Daniel suggests, by moving the decision making logic to a polymorphic
call on a Normal class. I say normal class, because I think going
from what you describe, you don't need an enum - you need a normal set
of classes.

Don't worry that you want to do different things with different
parameters, for each 'enum', this is solvable in a polymorphic way
too. (its the Strategy Pattern as Daniel says).

Essentially, keep the phrase 'Tell, don't ask' in mind when designing
your app, and this OO approach will naturally fall out.

Tell your objects to decide what they want to do, dont ask them for
information and then make the decision....


Andrew

 
Reply With Quote
 
Wojtek
Guest
Posts: n/a
 
      03-08-2007
andrewmcdonagh wrote :

> By using the enum in this way and having code spread throughout your
> app which checks which enum is being referenced to decide what to do,
> it sounds like your design needs to be 'normalised' in an OO way


I can see that, except that I have delibrately de-normalized between
use cases. The use cases are pretty well separated from each other.

I can delete a use case without affecting any other use case. Except of
course that that functionality has gone, which may mean that the user
can no longer maintain helper tables. But it will run OK.

Everything else is in a framework. Those classes cannot be removed as
they are used everywhere.

So if an enum is in the framework, then it should NOT know about any
business logic which uses it.

For instance (putting on fire-proof-coat)
----------------
public class Value
{
// these are column IDs which we store in the database
// - do NOT change them, only add new ones
// - they must be unique
private static int LOGIC_AND_ID = 0;
private static int LOGIC_OR_ID = 1;

// these are column IDs which we store in the database
// - do NOT change them, only add new ones

public static enum Logic
{
/**
* All values must return true
*/
AND(LOGIC_AND_ID),

/**
* Any value can be true
*/
OR(LOGIC_OR_ID);

private Logic( int databaseID )
{
ivDatabaseID = databaseID;
}

private int ivDatabaseID;

public int getDatabaseID()
{
return ivDatabaseID;
}

/**
* Returns the Logic for a given database id number<br><br>
* Used to find a Logic from a Web page field or database column
*/
public static Logic getLogic( int databaseID )
throws EnumNotFoundException
{
for (Logic logic : Logic.values())
if (logic.getDatabaseID() == databaseID)
return logic;

throw new EnumNotFoundException( Logic.class.getName() + "(id: " +
databaseID + ")" );
}
}

// .. other universal values, such a number of milli-seconds in a
// second, minute, hour, day, and so forth
}
----------------

Mind you this is untested code. But it should work (famous last words).
At least the compiler does not complain

--
Wojtek


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Difference between enum class and enum struct Brian C++ 4 02-27-2010 04:03 PM
enum: display elements of an enum specified at runtime Jerminia Java 3 10-07-2005 10:08 PM
enum within an enum - Java 6 06-13-2005 12:51 AM
Including an enum within another enum, possible? mrhicks C Programming 2 06-10-2004 03:00 AM
How to enum an enum? Ernst Murnleitner C++ 5 11-13-2003 11:06 AM



Advertisments