是否可以使用Enum常量作为Java中可实例化类的模板?

时间:2012-07-07 08:12:57

标签: java class templates enums instantiation

对不起,如果我的问题有点不清楚;我觉得找到措辞有点困难。我花了几个小时在Eclipse中徘徊,巡航JavaDoc,谷歌,以及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

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

我认为枚举常量被设计为不可变的。这与我的想法没有冲突;我希望每个枚举常量表示一个可变类的不可变定义。

1 个答案:

答案 0 :(得分:2)

您可以这样做:

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());
}