【问题标题】:Is it possible to use Enum constants as templates for instantiable classes in Java?是否可以使用枚举常量作为 Java 中可实例化类的模板?
【发布时间】:2012-07-07 13:48:11
【问题描述】:

对不起,如果我的问题有点不清楚;我发现很难找到措辞。我花了几个小时在 Eclipse 中玩转,浏览 JavaDoc、Google 以及 SO。我学到了很多,但没有找到答案。

我想做的是定义一个枚举,例如:

public enum Animals {
    Cow,
    Chicken,
    Sheep,
    Horse;
}

并让每个枚举常量定义一个非本地类的可实例化类。下面的工作吗?如果不是,为什么?会是什么?

在某个文件中:

abstract public class Animal {

    private String nameString;

    public String getName() {
        return nameString;
    }

}

另一个:

public enum Animals {

    Cow ((new Animal() {
        private boolean hasMilk;
        {
            nameString = "Cow";
            hasMilk = false;
        }
        public boolean hasMilk() {
            return hasMilk;
        }
    }).getClass()),

    Chicken ((new Animal() {
        private boolean hasFeathers;
        {
            nameString = "Chicken";
            hasFeathers = true;
        }
        public boolean hasFeathers() {
            return hasFeathers;
        }
    }).getClass()),

    Sheep ((new Animal() {
        private boolean isShorn;
        {
            nameString = "Cow";
            isShorn = false;
        }
        public boolean isShorn() {
            return isShorn;
        }
        public void Shear() {
            isShorn = true;
        }
    }).getClass()),

    Horse ((new Animal() {
        {
            nameString = "Cow";
        }
    }).getClass());


    private Class<? extends Animal> animalClass;

    private Animals(Class<? extends Animal> a) {
        animalClass = a;
    }

    public Class<? extends Animal> getAnimalClass() {
        return animalClass;
    }
}

然后,在其他类的其他方法中,能够做到这一点:

Animal farmAnimal;
farmAnimal = Animals.Sheep.getAnimalClass().newInstance();
boolean shorn = farmAnimal.isShorn();

(此时shorn的值为false);

farmAnimal.shear();
shorn = farmAnimal.isShorn();

(shorn == true)

farmAnimal = Animals.Sheep.getAnimalClass().newInstance();
shorn = farmAnimal.isShorn();

(shorn == false)

显然,这不是我在这里所做的最好的方式,但这不是重点。我知道我可以为枚举常量指定行为,但这并不能使它们作为不同的实例多次实例化。我希望能够创建各种枚举常量的多个实例(或副本),具有不同的实例变量(以及不同数量/类型的实例变量),具有不同的访问器方法,然后我可以对其进行处理(更改实例变量)无需修改枚举常量。

我知道枚举常量被设计为不可变的。这与我的想法并不冲突;我希望每个枚举常量都代表一个可变类的不可变定义。

【问题讨论】:

    标签: java class templates enums instantiation


    【解决方案1】:

    你可以这样做:

    public enum AnimalType {
        COW {
            @Override
            public Animal createNew() {
                return new Cow();
            }
        },
        HORSE {
            @Override
            public Animal createNew() {
                return new Horse();
            }
        };
    
        public abstract Animal createNew();
    }
    
    public abstract class Animal {
        private final AnimalType type;
        private final String nameString;
    
        public Animal(final AnimalType type, final String nameString) {
            super();
            this.type = type;
            this.nameString = nameString;
        }
    
        public String getName() {
            return nameString;
        }
    
        public AnimalType getType() {
            return type;
        }
    }
    
    public class Horse extends Animal {
        public Horse() {
            super(AnimalType.HORSE, "Horse");
        }
    }
    
    public class Cow extends Animal {
        private boolean milk;
    
        public Cow() {
            super(AnimalType.COW, "Cow");
        }
    
        public boolean hasMilk() {
            return milk;
        }
    
        public void setMilk(final boolean milk) {
            this.milk = milk;
        }
    }
    
    @Test
    public void testEnum() {
        Cow cow = (Cow) AnimalType.COW.createNew();
        Horse horse = (Horse) AnimalType.HORSE.createNew();
    
        System.out.println("cow  : " + cow.getType() + ", has milk: " + cow.hasMilk());
        System.out.println("horse: " + horse.getType());
    }
    

    【讨论】:

    • 谢谢。据我所知,您的解决方案可以实现我所追求的最终结果,但感觉不是很令人满意。我可能要求一种实际上并不存在的语言功能。在一个有点相关的说明中,我有什么理由不应该将 Animal 声明中的所有 Animal 子类声明为嵌套类?这种事情(并将类定义组合为枚举常量)对我的组织方面很有吸引力。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多