Smuggling information to enums

R

Roedy Green

What the techniques are there for smuggling information to enums?

they don't have constructors. It is not clear how you would make
them nested classes.

Is it possible to somehow have two enum class objects in RAM at once,
each with different instance data?

Do you have to pass it in each time with the method or use static
setters?
--
Roedy Green Canadian Mind Products
http://mindprod.com

"Nature provides a free lunch, but only if we control our appetites."
~ William Ruckelshaus, America’s first head of the EPA
 
J

Jason Cavett

What the techniques are there for smuggling information to enums?

they don't have constructors.   It is not clear how you would make
them nested classes.

Is it possible to somehow have two enum class objects in RAM at once,
each with different instance data?

Do you have to pass it in each time with the method or use static
setters?
--
Roedy Green Canadian Mind Productshttp://mindprod.com

"Nature provides a free lunch, but only if we control our appetites."
~ William Ruckelshaus, America’s first head of the EPA

I'm not sure what you mean by "smuggling" information.

Enums can have constructors, though. See the following example (this
enum is inside the class ActionManager):

public enum DefaultActions {
CASCADE_WINDOW_ACTION(new CascadeWindowsAction()),
CLOSE_ALL_PROJECTS_ACTION(new CloseAllProjectsAction()),
CLOSE_ALL_WINDOWS_ACTION(new CloseAllWindowsAction());
// There are more actions, I'm just truncating it for posting
purposes.

/**
* Constructor
*
* @param action
* the action to place into the manager
*/
private DefaultActions(AbstractAction action) {
String key = this.toString();
ActionManager.put(key, action);
}

/**
* Convenience method for retrieving a default action.
*
* @return the action
*/
public AbstractAction getAction() {
return ActionManager.get(this.toString());
}
}
 
J

Joshua Cranmer

Roedy said:
Is it possible to somehow have two enum class objects in RAM at once,
each with different instance data?

If you muck around with ClassLoaders, yes. However, this approach leads
to such fun errors as this one:
java.lang.ClassCastException: util.Option cannot be cast to util.Option
 
A

Andreas Leitgeb

Roedy Green said:
What the techniques are there for smuggling information to enums?
they don't have constructors.

They *do* have constructors, though the only place they're called
from is the identifier list at the start of the enum-declaration.

enum FooBar {
FOO("Hello"), BAR(42), SNAFU(new Object());

FooBar(String s) { ... }
FooBar(int i) { ... }
FooBar(Object o) { ... }
}
In this example, each of the given constructors is used once.
It is not clear how you would make them nested classes.

Enums are always static, so unless I mix up something, they
cannot be nested classes.

You can write the enum such, that it obtains information from
another class, and hope that you can fill your information into
the other class, safely before your enum is loaded and retrieves
the information. But you cannot have more of them than one per
class loader.

Does it at least seem as if I had understood your question?
 
L

Lew

Andreas said:
Enums are always static, so unless I mix up something, they
cannot be nested classes.

They can be nested classes, they just can't be inner classes.

From the JLS, s. 8.9:
Nested enum types are implicitly static. It is permissable [sic]
to explicitly declare a nested enum type to be static.
 
L

Lew

Roedy said:
What the techniques are there for smuggling information to enums?

they don't have constructors.  

Answered by others.
It is not clear how you would make them nested classes.

public class Foo
{
enum Bar { PLUGH, XYZZY, SHAZAM }
...
}
Is it possible to somehow have two enum class objects in RAM at once,
each with different instance data?

An enum can only have as many instances as it has enum values. Each
of those instances can have different instance data, e.g. (untried,
untested, uncompiled),

public enum Suit
{
CLUBS( CLUB_IMAGE ), DIAMONDS( DIAMOND_IMAGE ),
HEARTS( HEART_IMAGE), SPADES( SPADE_IMAGE );

private Image aceImage;

Suit( Image image )
{ this.aceImage = image; }

public Image getAceImage()
{ return this.aceImage; }

public void setAceImage( Image image )
{ this.aceImage = image; }
}
Do you have to pass it in each time with the method or use static
setters?

Instance setters.
 
A

Andreas Leitgeb

Lew said:
They can be nested classes, they just can't be inner classes.

Ok, so I *did* mix up something.

Anyway, I think from the context, that Roedy also meant inner
since making them nested (but not inner) wouldn't be
any problem, whatsoever.
 
J

Jon Gómez

Joshua said:
If you muck around with ClassLoaders, yes. However, this approach leads
to such fun errors as this one:
java.lang.ClassCastException: util.Option cannot be cast to util.Option

I thought, "That really does sound like fun!" After a while, I managed
to get a similar message. :)
Jon.
 
R

Roedy Green

Enums can have constructors, though. See the following example (this
enum is inside the class ActionManager):

The terminology gets confusing. The enum constants have constructors,
but they not mechanisms whereby you can get information from outside
the enum into it so that its methods for example can have some tuning
constants for a particular incarnation of the enum associated with
some class.

Another way of putting it is there is no constructor for the enum as a
whole, just a template for the individual enum constant constructors.
--
Roedy Green Canadian Mind Products
http://mindprod.com

"Nature provides a free lunch, but only if we control our appetites."
~ William Ruckelshaus, America’s first head of the EPA
 
L

Lew

Roedy said:
The terminology gets confusing. The enum constants have constructors,
but they not mechanisms whereby you can get information from outside
the enum into it so that its methods for example can have some tuning
constants for a particular incarnation of the enum associated with
some class.

Would regular setter methods suffice for what you're trying to do?

It does make for some contradiction of the idea that an enum constant
is, well, constant, but it might make a good hack for your purposes.
Watch your thread safety, though.
 
R

Roedy Green

Does it at least seem as if I had understood your question?

Yes, you understood. I was hoping I had overlooked something.

In my case I was rewriting my CSVReader to use enums. A CSVReader can
be configured with the various characters you want to use for
separator, quote and comment. The enum needs to know these facts.
Further there could be two different CSVReader objects in RAM at once.
That means I would want two versions of the enum, each with a
different set of instance data.

I think the way it will have to work is pass in the magic constants on
every call as parameters so that only one uncustomised copy of the
enum is needed.

The parms on the enum constant constructors pretty well have to be
constants, or something public and static since almost nothing is
known in the context of those parms.

--
Roedy Green Canadian Mind Products
http://mindprod.com

"Nature provides a free lunch, but only if we control our appetites."
~ William Ruckelshaus, America’s first head of the EPA
 
R

Roedy Green

nyway, I think from the context, that Roedy also meant inner

since making them nested (but not inner) wouldn't be
any problem, whatsoever.

I meant nested. Inner would obviously be preferable, but I thought
perhaps there might be some way of passing information to a static
nested class. Enums are certainly a peculiar kind of static nested
class. You can't do new on them. They have no constructor.
--
Roedy Green Canadian Mind Products
http://mindprod.com

"Nature provides a free lunch, but only if we control our appetites."
~ William Ruckelshaus, America’s first head of the EPA
 
R

Roedy Green

Perhaps you might try a less colorful and more mundane term
than "smuggling" to explain what you want to do ..

"get" information from the outside world into the enum for its use. It
seems to be doing all it can to prevent me. I was prepared to jump
through some hoops to get a small amount of data in. Hence the term
"smuggling".

--
Roedy Green Canadian Mind Products
http://mindprod.com

"Nature provides a free lunch, but only if we control our appetites."
~ William Ruckelshaus, America’s first head of the EPA
 
L

Lew

Roedy said:
I meant nested. Inner would obviously be preferable, but I thought
perhaps there might be some way of passing information to a static
nested class.  Enums are certainly a peculiar kind of static nested
class. You can't do new on them. They have no constructor.

I wish you'd stop misleading people. Enums do have constructors, much
as utility classes with private constructors have them. In both
cases, client code cannot create new instances of the class willy-
nilly, but that is not the same thing as lacking a constructor.

Consider:

public final class TypeSafeEnum
{
public static final TypeSafeEnum FOO = new TypeSafeEnum( "foo" );
public static final TypeSafeEnum BAR = new TypeSafeEnum( "bar" );

private final String name;
private TypeSafeEnum( String name )
{
this.name = name;
}
public String getName()
{
return this.name;
}
}

This class, too, has a constructor, but client code cannot do a 'new'
on it. Perfectly standard Java idiom.

There's still a way to pass information to this class as there is with
enums - add a mutator and some state for it to mutate.
 
M

Mark Space

Roedy said:
"get" information from the outside world into the enum for its use. It
seems to be doing all it can to prevent me. I was prepared to jump
through some hoops to get a small amount of data in. Hence the term
"smuggling".


Why use enums? Enums are constants that don't change. If you are
reading data from the outside world, those aren't really enums.

I'd read the values you need into some custom object then dump the
object into a HashSet (or HashMap). Then you can implement your own
identity semantics on those objects, just like enum does, but with out
the restrictions that makes enums difficult to work with in these
situations.

The real question is: what are you actually trying to do here? What
kind of operations do you envision for these objects? Total, not just
the ones you think would be really cool for an enum. Don't forget "read
and write" because apparently that's what messing you up here.
 
R

Roedy Green

Instance setters.

But there is still only one instance of the enum. If you change it, I
change it for all clients of the enum. That is really the problem.
Thanks for finally making that clear.
--
Roedy Green Canadian Mind Products
http://mindprod.com

"Nature provides a free lunch, but only if we control our appetites."
~ William Ruckelshaus, America’s first head of the EPA
 
R

Roedy Green

They can be nested classes, they just can't be inner classes.

That's a step in the right direction, but you would need an inner
class for the enum to be able to extract information from the mother
object. There is no way to pass the address of the mother object to
the enum if it is static.

I think the key is to think of enums as resolutely static.
--
Roedy Green Canadian Mind Products
http://mindprod.com

"Nature provides a free lunch, but only if we control our appetites."
~ William Ruckelshaus, America’s first head of the EPA
 
L

Lew

Roedy said:
... you would need an inner
class for the enum to be able to extract information from the mother
object.  There is no way to pass the address of the mother object to
the enum if it is static.

Oh, but there most definitely is a way:

MyEnum.FOO.setMother( this );

Note: not easy to make thread safe.
I think the key is to think of enums as resolutely static.

Yes.
 
M

Mark Rafn

Roedy Green said:
In my case I was rewriting my CSVReader to use enums. A CSVReader can
be configured with the various characters you want to use for
separator, quote and comment. The enum needs to know these facts.

I think you're using the wrong hammer. An enum is static. Anything it
"knows" is shared among all uses of the enum value. What you want is
something like a context or configuration object, that can be created once per
CSV file, and knows the settings for that file.
Further there could be two different CSVReader objects in RAM at once.
That means I would want two versions of the enum, each with a
different set of instance data.

Yeah, that's not an enum.
I think the way it will have to work is pass in the magic constants on
every call as parameters so that only one uncustomised copy of the
enum is needed.

Or setters on the CSVReader instance, or a CSVConfig object that's passed
around, or any of a bunch of other options.
The parms on the enum constant constructors pretty well have to be
constants, or something public and static since almost nothing is
known in the context of those parms.

You can calculate them at runtime, but they should be the same throughout the
JVM's (or at least the classloader's) lifetime.
 
J

John B. Matthews

Roedy Green said:
"get" information from the outside world into the enum for its use. It
seems to be doing all it can to prevent me. I was prepared to jump
through some hoops to get a small amount of data in. Hence the term
"smuggling".


Here's an example that initializes a static glossary from a properties
file. Each enum can then access its glossary entry by name:

<http://sites.google.com/site/drjohnbmatthews/composite/source-code>
 

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

Similar Threads

JDK 1.6.0_13 is out 6
Class-inheritance icon 1
ReadyBoost 12
Loving Enums 2
scope rules in enums 4
Dual View Enums 0
How to prevent code repetition with enums? 5
In praise of Java 1.5 enums 25

Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,682
Members
48,796
Latest member
Greg L.

Latest Threads

Top