Java Forum / General / December 2005
Question about Typesafe Enums
Rhino - 14 Dec 2005 15:50 GMT I'm trying to incorporate some of the new features of Java 1.5 into some of my existing classes but I'm somewhat confused about how to do something with specific with typesafe enums.
The main article in the SDK documentation is http://java.sun.com/j2se/1.5.0/docs/guide/language/enums.html. Based on that article, I'd like to go a beyond something they show in the Planets example. I need the guidance of those of you who understand this better to tell me if I can do what I want to do. I don't have the terminology straight in my mind yet so forgive me if I don't articulate this correctly.
In the Planet enum that is shown in the article, they have a list of planets and each planet has two specific values, a mass and a radius. The enum provides methods mass() and radius() to get those values when they are needed. Therefore, if I want to get the mass of the Earth, my class can get it via Planet.EARTH.mass(), e.g.
System.out.println("The mass of the Earth is " + Planet.EARTH.mass());
So far so good. Now, would it be possible to set up other enums to correspond to the values associated with the planets and use them to reference the values? For example, could I create an enum called Mass that was associated with the mass of each planet, then refer to the mass of a specific planet via the new enum, something like this:
System.out.println("The mass of the Earth is " + Planet.EARTH.Mass);
I'm not wedded to the syntax in that last example; in fact, it looks a bit nasty to me. I'm just trying to indicate that it would use the new Mass enum instead of the mass() method to refer to the first value associated with the given planet.
It would be neat to be able to avoid writing methods like mass() and just use additional enums like Mass to refer to the specific facts that I want. Basically, I'd like to be able to use meaningful words like Mass, rather than numbers, as subscripts to the implied array that is in the Planet enum.
How could I do what I want to do? And, maybe more importantly, would it be a good idea or would it cause problems?
 Signature Rhino
Hendrik Maryns - 14 Dec 2005 16:29 GMT Rhino schreef:
> I'm trying to incorporate some of the new features of Java 1.5 into some of > my existing classes but I'm somewhat confused about how to do something with [quoted text clipped - 16 lines] > > So far so good. Indeed.
Now, would it be possible to set up other enums to
> correspond to the values associated with the planets and use them to > reference the values? For example, could I create an enum called Mass that [quoted text clipped - 7 lines] > instead of the mass() method to refer to the first value associated with the > given planet. I don´t think you can do this sort of hard-linking two enums together, but you could define mass() to return something of type Mass, and in the initialisation of Earth tell it to return Mass.EARTH_MASS.
> It would be neat to be able to avoid writing methods like mass() and just > use additional enums like Mass to refer to the specific facts that I want. > Basically, I'd like to be able to use meaningful words like Mass, rather > than numbers, as subscripts to the implied array that is in the Planet enum. Why would you want to have anything to do with those numbers? Although they are used by the JVM internally, there is absolutely no to access them. And how do you see this connected to Mass?
> How could I do what I want to do? What DO you want to do?
And, maybe more importantly, would it be a
> good idea or would it cause problems? Doesn´t seem like a good idea, but you are really unclear.
H.
 Signature Hendrik Maryns
================== www.lieverleven.be http://aouw.org
Rhino - 14 Dec 2005 17:45 GMT Rhino schreef:
> I'm trying to incorporate some of the new features of Java 1.5 into some > of my existing classes but I'm somewhat confused about how to do something [quoted text clipped - 17 lines] > > So far so good. Indeed.
Now, would it be possible to set up other enums to
> correspond to the values associated with the planets and use them to > reference the values? For example, could I create an enum called Mass that [quoted text clipped - 7 lines] > enum instead of the mass() method to refer to the first value associated > with the given planet. I don´t think you can do this sort of hard-linking two enums together, but you could define mass() to return something of type Mass, and in the initialisation of Earth tell it to return Mass.EARTH_MASS.
> It would be neat to be able to avoid writing methods like mass() and just > use additional enums like Mass to refer to the specific facts that I want. > Basically, I'd like to be able to use meaningful words like Mass, rather > than numbers, as subscripts to the implied array that is in the Planet > enum. Why would you want to have anything to do with those numbers? Although they are used by the JVM internally, there is absolutely no to access them. And how do you see this connected to Mass?
> How could I do what I want to do? What DO you want to do?
And, maybe more importantly, would it be a
> good idea or would it cause problems? Doesn´t seem like a good idea, but you are really unclear.
H.
================================================= I was going to intersperse my followups within your post, just like you did to mine, but my newsreader isn't co-operating by putting >> in front of my original words and > in front of your reply....
I'm sorry to be so unclear; like I said, I'm still strugging with the terminology. Let me try explaining it a bit differently.
Okay, let's say we have an array called Planet and it looks like this (I'll just use the inner planets to minimize typing): Object[][] Planet = { {"Mercury", 3.303e+23, 2.4397e6, 0}, {"Venus", 4.869e+24, 6.0518e6, 0}, {"Earth", 5.976e+24, 6.37814e6, 1}, {"Mars", 6.421e+23, 3.3972e6, 1} };
In this array, the first column contains a planet name, the second column contains the mass of the planet, the third column contains the radius of the planet, and the fourth column contains the number of natural satellites that the planet has.
If I want to know the number of satellites for the planet Mars, I can get it via this: Planet[3][3]. But the meanings of the '3's in the subscripts are not terribly obvious to someone looking at the code; no one would have any way of knowing the _meaning_ of the fourth row or the fourth column of the array.
I'd much rather be able to reference the number of satellies for a planet with syntax that demonstrates a knowledge of the nature of the data, i.e. the first column contains the planet's name, the fourth column is the number of satellites, etc. To my way of thinking, this array has (implied) column names and those column names comprise an enum consisting of the values NAME, MASS, RADIUS, and SATELLITES. Also, the individual rows of the array can be uniquely identified by the planet name which is therefore an implied enum too, consisting of the values Mercury, Venus, Earth and Mars.
I'm not sure how the syntax should look but I'm picturing something that has words from enums in place of numeric subscripts, something like this: Planet["Mars"][SATELLITES], which means 'the number-of-satellites value from the row of the array Planet whose key (first column value) is "Mars"'.
Again, this syntax is probably not entirely appropriate for maintaining consistentcy with other syntax in Java but it gives the flavour I am looking for.
I would also like to be able to use variables so that it would be possible to loop through the array and list the number of satellites for each planet without using a numeric subscript. Something like:
for (String name, int satellites : Planet) { System.out.println("Planet " + name + " has " + Planet[NAME][SATELLITES] + " satellites."); }
Sorry, I know that won't compile as it is. I'm not trying to make a firm proposal on what the syntax should be, I'm just trying to convey the flavour of what I'd like to do.
It seems to me that Enums are the vital ingredient in making this work but I may be perverting them beyond their intended use. Or maybe there is a much better way to do this without using Enums at all.
I'm just looking for some feedback on whether the concept I'm exploring even makes sense and, if it does, how could I accomplish it with typesafe enums?
Rhino
ricky.clarkson@gmail.com - 14 Dec 2005 18:23 GMT Planet[] planets= { new Planet("Mercury", 3.303e+23, 2.4397e6, 0), new Planet("Venus", 4.869e+24, 6.0518e6, 0), new Planet("Earth", 5.976e+24, 6.37814e6, 1), new Planet("Mars", 6.421e+23, 3.3972e6, 1) };
final class Planet { private final String name; private final double mass; private final double radius; private final int satellites;
public Planet (final String name,final double mass,final double radius,final int satellites) { this.name=name; this.mass=mass; this.radius=radius; this.satellites=satellites; }
public String getName() { return name; }
public double getMass() { return mass; }
public double getRadius() { return radius; }
public int numberOfSatellites() { return satellites; } }
Find a tutorial on OOP sometime.
Rhino - 14 Dec 2005 19:52 GMT > Planet[] planets= > { [quoted text clipped - 43 lines] > > Find a tutorial on OOP sometime. Actually, I based my question on an article in the Java 1.5 SDK. I cited that fact in the first post in this thread.
The code you provided is essentially the same as the code in that article, which _doesn't_ answer my question.
Rhino
Thomas Hawtin - 14 Dec 2005 22:36 GMT > http://java.sun.com/j2se/1.5.0/docs/guide/language/enums.html. [...]
> System.out.println("The mass of the Earth is " + Planet.EARTH.Mass); > > I'm not wedded to the syntax in that last example; in fact, it looks a bit > nasty to me. I'm just trying to indicate that it would use the new Mass enum > instead of the mass() method to refer to the first value associated with the > given planet. I'm not entirely sure as to what you want here. An enum has a limited set of values, but mass is a (near) continuous quantity. So, an enum of mass doesn't make sense.
I'll assume you want an enumeration of properties (mass, radius, etc), which can be applied to any Planet. So that you can write a method that prints a property of a given planet, but is general to any property. Here's a way to do that.
enum PlanetMeasure { RADIUS { public double of(Planet planet) { return planet.radius(); }, MASS { public double of(Planet planet) { return planet.mass(); }, ; public abstract double of(Planet planet); }
static void printPlanetMeasure( Planet planet, PlanetMeasure property ) { System.out.println( "The "+property+" of "+planet+" is " + property.of(planet) ); }
(I was going to call the method "value" instead of "of", but that kind of clashes with the namings of the enum infrastructure. I'm not entirely happy with either. "of" is far too cute.)
Obviously, it gets more complicated if you want to use properties of different types.
Tom Hawtin
 Signature Unemployed English Java programmer http://jroller.com/page/tackline/
Rhino - 15 Dec 2005 00:34 GMT >> http://java.sun.com/j2se/1.5.0/docs/guide/language/enums.html. [...] > [quoted text clipped - 6 lines] > > I'm not entirely sure as to what you want here. Yeah, I'm not having a lot of luck articulating my wishes in a way that seems clear even to me, let alone anyone else ;-)
> An enum has a limited set of values, but mass is a (near) continuous > quantity. So, an enum of mass doesn't make sense. > > I'll assume you want an enumeration of properties (mass, radius, etc), > which can be applied to any Planet. Yes, that's right!
I didn't put it very well, did I? ;-) It obviously makes no sense to have an enumerations that contains all the values possible for a planetary mass. I should have made it clearer that I wanted to enumerate the _properties_ of a planet. Those would be relatively few, such as mass and radius, and would lend themselves better to an enum.
Then I want to use the names of the properties to access the actual values so that I can say something like Planet.EARTH.MASS to get the mass of the Earth.
> So that you can write a method that prints a property of a given planet, > but is general to any property. Here's a way to do that. [quoted text clipped - 24 lines] > clashes with the namings of the enum infrastructure. I'm not entirely > happy with either. "of" is far too cute.) I *think* you're on the right track but....
I got several errors when I tried to compile the PlanetMeasure class in Eclipse. Frankly, I'm somewhat confused by what you're doing (not surprising since I've asked an unclear question!) that it wasn't obvious to me why these errors were arising. I took a guess and found that the following compiled fine, although I don't know if it changes the intent of your code....
=============================================== public enum PlanetMeasure {
RADIUS { public double of(Planet planet) { return planet.radius(); } }, MASS { public double of(Planet planet) { return planet.mass(); } }, ; public abstract double of(Planet planet);
static void printPlanetMeasure(Planet planet, PlanetMeasure property) { System.out.println("The " + property + " of " + planet + " is " + property.of(planet)); } } ================================================
Now, even if I've made reasonable alterations in the code, I'm not quite clear how to use what you've done; how/where do I specify the _values_ of the mass and radius for each of my planets so that I can get them back out again with the of() method?
> Obviously, it gets more complicated if you want to use properties of > different types. If you can help me understand what you've done so far, I might be able to work out the rest on my own....
Rhino
Thomas Hawtin - 15 Dec 2005 01:14 GMT > I got several errors when I tried to compile the PlanetMeasure class in Yup, I got my indentation and hence braces out.
> Now, even if I've made reasonable alterations in the code, I'm not quite > clear how to use what you've done; how/where do I specify the _values_ of > the mass and radius for each of my planets so that I can get them back out > again with the of() method? They're still in the original Planet enum. If you really wanted to, you could switch on planet within each of the PlanetMeasures.of implementations. Or (worse still), replace the "of" method with methods for Mercury, Mars, ..., Xena.
Tom Hawtin
 Signature Unemployed English Java programmer http://jroller.com/page/tackline/
Roedy Green - 14 Dec 2005 23:45 GMT On Wed, 14 Dec 2005 10:50:03 -0500, "Rhino" <no.offline.contact.please@nospam.com> wrote, quoted or indirectly quoted someone who said :
>So far so good. Now, would it be possible to set up other enums to >correspond to the values associated with the planets and use them to >reference the values? For example, could I create an enum called Mass that >was associated with the mass of each planet, then refer to the mass of a >specific planet via the new enum, something like this: no, but you could add a field or a method to the enum constants.
Unfortunately you can't extend an enum. So you have to modify the original enum class code.
 Signature Canadian Mind Products, Roedy Green. http://mindprod.com Java custom programming, consulting and coaching.
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|