有许多方法可以做到这一点,假设你的品种意味着“创造我的孩子”.
反射
首先是使用反射.如果你的类有一个no-args构造函数,这就像调用Class.newInstance一样简单:
public Animal breed() {
try {
return (Animal) getClass().newInstance();
} catch (Exception ex) {
// TODO Log me
return null;
}
}
如果你的所有子类中都没有no-args构造函数,那么你必须在所有子类中都有一个统一的构造函数.例如,如果你有Cat(int,String)和Dog(int,String),那么你需要通过Class.getConstructor获取构造函数并在其上调用newInstance:
return (Animal) getClass().getConstructor(int.class, String.class).newInstance(0, "Unnamed");
例如,int和String可以是年龄和名称.这就是你用反射做到这一点的方法.
供应商
另一种方法是使用这个简单的界面:
public interface Provider {
T create();
}
然后让您的抽象类在其构造函数中获取此实例:
public abstract class Animal {
private final Provider animalProvider;
protected Animal( ... , Provider animalProvider) {
// ...
this.animalProvider = animalProvider;
}
public Animal breed() {
return animalProvider.create();
}
}
然后您的子类将传递Provider< Animal>到将创建子类的新实例的超类:
public class Dog extends Animal {
public Dog( ... ) {
super( ... , new DogProvider());
// ...
}
private static class DogProvider implements Provider {
public Animal create() {
return new Dog( ... );
}
}
}
对其他子类也这样做.
注意:如果你的品种意思是“得到我的类型”,那么你应该编辑你的问题来说明.如果这是你的意思,那么这是一个可行的解决方案:
public abstract class Animal {
protected final Breed breed;
protected Animal( ... , Breed breed) {
// ...
this.breed = breed;
}
public Breed getBreed() {
return breed;
}
}
我建议遵循数据容器方法的get / set约定. Java具有设计用于处理这些命名约定的bean类,并且它或多或少是许多平台的标准.对于您的子类:
public class Dog extends Animal {
public Dog( ... ) {
super( ... , new Breed( ... ));
// ...
}
}