views:

165

answers:

2

Hi,

I have an enum, which looks like

public enum Animal {
  ELEPHANT,
  GIRAFFE,
  TURTLE,
  SNAKE,
  FROG
}

and I want to do something like

Animal frog = Animal.FROG;
Animal snake = Animal.SNAKE;

boolean isFrogAmphibian = frog.isAmphibian(); //true
boolean isSnakeAmphibian = snake.isAmphibian(); //false

boolean isFrogReptile = frog.isReptile(); //false
boolean isSnakeReptile = snake.isReptile(); //true

boolean isFrogMammal = frog.isMammal(); //false
boolean isSnakeMammal = snake.isMammal(); //false

I simplified the example for didactic purposes, but this would be really useful to me for my real life example. Can I do it in Java?

+4  A: 

Yes, you can. It would look like this:

public enum Animal {
  ELEPHANT(false),
  GIRAFFE(false),
  TURTLE(false),
  SNAKE(false),
  FROG(true);

  private final boolean isAmphibian;

  Animal(boolean isAmphibian) {
    this.isAmphibian = isAmphibian;
  }

  public boolean isAmphibian() {
    return this.isAmphibian;
  }
}

Then you would call it like:

Animal.ELEPHANT.isAmphibian()

danben
constructors to Enums should be private
fuzzy lollipop
Not "should be private", but must be private.
Steve Kuo
That's strange - the Planet example at http://java.sun.com/j2se/1.5.0/docs/guide/language/enums.html doesn't use the private modifier on the constructor. Are you sure?
danben
Not needed. They're implicitly already private. Enumns are uninstantiable at any way.
BalusC
+6  A: 

yes Enum is a class in Java.

public enum Animal 
{
  ELEPHANT(true),
  GIRAFFE(true),
  TURTLE(false),
  SNAKE(false),
  FROG(false);

  private final boolean mammal; 
  private Animal(final boolean mammal) { this.mammal = mammal; }
  public boolean isMammal() { return this.mammal; }
}

but in your case for a real system I would make that an Enum as well since there is a fixed set of types of animals.

public enum Type
{
  AMPHIBIAN,
  MAMMAL,
  REPTILE,
  BIRD
}

public enum Animal 
{
  ELEPHANT(Type.MAMMAL),
  GIRAFFE(Type.MAMMAL),
  TURTLE(Type.REPTILE),
  SNAKE(Type.REPTILE),
  FROG(Type.AMPHIBIAN);

  private final Type type; 
  private Animal(final Type type) { this.type = type; }
  public boolean isMammal() { return this.type.equals(Type.MAMMAL); }
  public boolean isAmphibian() { return this.type.equals(Type.AMPHIBIAN); }
  public boolean isReptile() { return this.type.equals(Type.REPTILE); }
  // etc...
}

Also note that it is important to make any instance variable final as well.

fuzzy lollipop
what if I want different categories, like mammal, amphibian, reptile?
Samuel Carrijo
you would need multiple boolean flags for each one, or you could make that category and Enum as well as I suggest in my solution.
fuzzy lollipop
@fuzzy: I think there is a ';' missing between the last constant end the *class body*: `FROG(false) ; private final boolean mammal;` (And missing some return types...)
Carlos Heuberger
@fuzzy: Java requires that the enum body declarations - if there are any - be started by a ';', See JLS 8.9. Compiling with Java 1.6 (5 seconds): `Animal.java:9: ',', '}', or ';' expected \n private final boolean mammal;` (\n inserted to mark new line and position of error) The `Type` enum above don't need it since there are no body declarations...
Carlos Heuberger
Why are the methods private?
BalusC
not methods, CONSTRUCTORS you should not be able to create an instance of an Enum outside itself. Making the CONSTRUCTOR private means only the static instances on itself can create instances.
fuzzy lollipop
I was not talking about constructors. I literally said "methods". But I see that you already edited the methods to be public :) That looks better now, +1. BTW: enums doesn't necessarily need to have private c'tors. They are implicitly already private. Enums are uninstantiable. They are not classes.
BalusC
Oh and declaring an enum c'tor as `public` won't even make it to compile. I think you're confusing it a bit too much up with the good ol' pre-Java5 "typesafe class pattern".
BalusC
explicit is always better than implicit
fuzzy lollipop