0

Here is some enum with get() method.

public class ZooTest {

    public enum Animals {

        CHLOE("cat"),
        MOLLY("dog"),
        LUNA("cat"),
        TOBY("dog"),
        ZOE("parrot"),
        SNICKERS("cat");

        private final String type;

        Animals(String type) {
            this.type = type;
        }

        public class Animal {
        }

        public class Cat extends Animal {
        }

        public class Dog extends Animal {
        }

        public class Parrot extends Animal {
        }

        public Animal get() {
            return "cat".equals(type)
                    ? new Cat()
                    : "dog".equals(type)
                            ? new Dog()
                            : new Parrot();
        }
    }

    @Test
    public void shouldReturnSpecificClass() {
        assertTrue(Animals.CHLOE.get() instanceof Cat);
    }

    @Test(expectedExceptions = {ClassCastException.class})
    public void shouldReturnSpecificClass2() {
        Dog dog = (Dog) Animals.CHLOE.get();
    }
}

The question is how can it be improved to return specific type of animal without using type casting outside enum. Of course I can use methods like

public <T extends Animal> T get(Class<T> clazz) { return (T) get(); } 

but maybe there is less clumsy way.

4
  • 2
    This looks like something an enum is rather unsuited for. Perhaps better to have each animal as an instance, with the type noted with an enum inside an "animal" class? Enums are used for values that don't change, a property which doesn't intuitively apply to a list of animals. Commented Apr 22, 2015 at 10:35
  • and get rid of the String constants. Here, it seems you can use the class objects instead (like Cat.class). Commented Apr 22, 2015 at 10:38
  • 2
    Question: what do you intend to achieve using this design? Commented Apr 22, 2015 at 10:39
  • @Jägermeister Let's say it's a puzzle - I'm trying to understand how to break through java type erasure problem in case of design with enums. Commented Apr 23, 2015 at 8:48

3 Answers 3

2

This answer is based on assumption that you don't actually need separate instances of Cat for CHLOE, LUNA, or SNICKERS. Also since your Animals didn't have any methods or state it doesn't look like you really need them as separate classes. So maybe something like this will be easier:

public enum AnimalType {
    Cat, Dog, Parrot;
}

public enum Animals {

    CHLOE(AnimalType.Cat),
    MOLLY(AnimalType.Dog),
    LUNA(AnimalType.Cat),
    TOBY(AnimalType.Dog),
    ZOE(AnimalType.Parrot),
    SNICKERS(AnimalType.Cat);

    private final AnimalType type;

    Animals(AnimalType type) {
        this.type = type;
    }

    public AnimalType get() {
        return type;
    }
}
Sign up to request clarification or add additional context in comments.

Comments

2

You can create an abstract method get that and each instance of Animals has to implement:

 public enum Animals {

        CHLOE("cat") {
           @Override
           public Animal get() { return new Cat(); }
        },
        MOLLY("dog") {
           @Override
           public Animal get() { return new Dog(); }
        }
        //... and so on

        public abstract Animal get();
    }

3 Comments

Unfortunately even CHLOE("cat") { public Cat get() { return new Cat(); } } will not allow Cat cat = Animals.CHLOE.get();
my error is "incompatible types:Animals.Animal cannot be converted to Animals.Cat".
Oh! You are right. This is beacuse the type has to be Animal, like: Animal cat = Animals.CHLOE.get(). It is an Animal reference but an Cat concrete instance.
0

You have two mistakes of enum using. The first enum entities must provided something like type not instance (how it pointed Quirliom), and then your Animal enum must contains members cat, dog etc. The second unfortunately you can not extend any class from enum.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.