2

I'd like to know if it is possible in Java to nest Enums.

Here what i'd like to be able to do :

Have an enum Species made of CAT and DOG wich would grant me access to sub enums of the available CAT and DOG breeds. For example, i'd like to be able to test if wether a CAT or a DOG and if an animal is a PERSAN CAT or a PITBULL DOG. CAT and DOG breeds must be distinct enums ,i.e a CatBreeds enum and a DogBreeds enum.

Here is an example of access pattern i'd like to use :

Species :

  • Species.CAT
  • Species.DOG

Breeds :

  • Species.CAT.breeds.PERSAN
  • Species.DOG.breeds.PITBULL
Mathieu
  • 23
  • 2
  • To be a more precise, i have to manage different type of Item ( this is my 1st enum dimnension ). An item got some attribute and a map Detail. The 2nd enum dimension might be use to define the map's key of Detail avaibles for a given type of Item. – Mathieu Apr 14 '10 at 11:39

3 Answers3

3

Wouldn't you be better doing this with inheritance? Cat and Dog would be subclasses of Species. Persion would be a subclass of Cat and Pitbull would be a subclass of Dog.

What are trying to achieve by wanting to use Enums?

Tarski
  • 5,360
  • 4
  • 38
  • 47
  • I only got 2 classes, and dont need the other ones. Using inheritance is a bit too verbose and prevent me to use "type" based criteria selection or "type and subtype" based criteria selection. – Mathieu Apr 14 '10 at 11:41
  • 1
    There is ] at the end of your link. Understand the selection word as filtering. – Mathieu Apr 14 '10 at 12:39
  • Thanks Mathieu. Corrected comment: Well, if "type"-based criteria selection is what I think it means, then this may be a code smell. See http://hanuska.blogspot.com/2006/08/swich-statement-code-smell-and.html – Bert F Apr 14 '10 at 16:05
0

one way to nest enums:

package nested2;
import java.util.*;
interface HasChildren {
    Set<Enum<? extends HasChildren>> children();
    Class parent();
    Enum<? extends HasChildren> p();
}
enum Citrus implements HasChildren {
    lemon, lime, orange;
    Enum<? extends HasChildren> p;
    Class parent = getDeclaringClass();
    Class children;
    public Enum<? extends HasChildren> p() {
        return p;
    }
    public Class parent() {
        return parent;
    }
    public Set<Enum<? extends HasChildren>> children() {
        return children != null ? EnumSet.allOf(children) : null;
    }
    enum Orange implements HasChildren {
        navel, valencia, blood;
        Enum p;
        Class parent = getDeclaringClass();
        Class children;
        public Enum<? extends HasChildren> p() {
            return p;
        }
        public Class<Enum<? extends HasChildren>> parent() {
            return parent;
        }
        public Set<Enum<? extends HasChildren>> children() {
            return children != null ? EnumSet.allOf(children) : null;
        }
        enum Navel implements HasChildren {
            washinton, lateLane, caraCaraPink;
            Enum<? extends HasChildren> p;
            Class parent = getDeclaringClass();
            Class children;
            public Enum<? extends HasChildren> p() {
                return p;
            }
            public Class parent() {
                return parent;
            }
            public Set<Enum<? extends HasChildren>> children() {
                return null;
            }
        }
        static {
            navel.children = Navel.class;
            for (Navel n : Navel.values())
                n.p = orange;
            navel.p = navel;
        }
        enum Blood implements HasChildren {
            moro, taroco;
            Enum<? extends HasChildren> p;
            Class parent = getDeclaringClass();
            Class children;
            public Enum<? extends HasChildren> p() {
                return p;
            }
            public Class parent() {
                return parent;
            }
            public Set<Enum<? extends HasChildren>> children() {
                return null;
            }
        }
        static {
            blood.children = Blood.class;
            for (Blood b : Blood.values())
                b.p = blood;
            blood.p = orange;
        }
    }
    static {
        for (Orange o : Orange.values())
            o.p = orange;
        orange.children = Orange.class;
    }
}
public class EnumTree {
    static void visit(Class<?> clazz) {
        Object[] enumConstants = clazz.getEnumConstants();
        if (enumConstants[0] instanceof HasChildren) for (Object o : enumConstants)
            visit((HasChildren) o, clazz.getName());
    }
    static void visit(HasChildren hasChildren, String prefix) {
        if (hasChildren instanceof Enum) {
            System.out.println(prefix + ' ' + hasChildren + " (" + hasChildren.parent() + ")" + " (" + hasChildren.p()
                    + " " + ((Enum) hasChildren).getDeclaringClass());
            if (hasChildren.children() != null) for (Object o : hasChildren.children())
                visit((HasChildren) o, prefix + ' ' + hasChildren);
        } else
            System.out.println("other " + hasChildren.getClass());
    }
    static <E extends Enum<E> & HasChildren> Set<E> foo() {
        return null;
    }
    public static void main(String[] args) {
        //looks like p is the right parent
        System.out.println(Citrus.Orange.Navel.washinton);
        System.out.println(Citrus.Orange.Navel.washinton.getClass().getDeclaredClasses());
        System.out.println(Citrus.Orange.Navel.washinton.getClass().getEnclosingClass());
        System.out.println(Citrus.Orange.Navel.washinton.getClass().getDeclaringClass());
        visit(Citrus.lemon, "");
        System.out.println("----------------------");
        visit(Citrus.orange, "");
        System.out.println("----------------------");
        visit(Citrus.class);
        System.out.println("----------------------");
    }
}
Ray Tayek
  • 9,841
  • 8
  • 50
  • 90
-1
public enum A {

    a1, 
    a2;

    public enum B {
        b1, 
        b2
    }
}

and so on...

thelost
  • 6,638
  • 4
  • 28
  • 44
  • 2
    Neat - it is a nested enum and it might be the best he gets. However, this gives "Species.breeds.PERSAN" instead of the "Species.CAT.breeds.PERSAN" that he wants. – Bert F Apr 14 '10 at 12:07