假设你有一个班级人口和人口是一个内部的个人名单。用户希望将未构造的Individual子类传递给Population,并让Population完成构造这些子类的工作,无论传递什么子类。
public class Population{
private List<Individual> indiList = new ArrayList(25);
/*I know this won't work for multiple reasons, but shows the idea*/
public void addIndividualsOfType(Individual individual){
for (ListIterator it = indiList.listIterator(); it.hasNext(); ){
it.next()
it.add(individual.construct(param1, param2, param3);
}
}
}
public abstract class Individual{
SomeType param1;
...
public Individual(SomeType param1, SomeType param2, SomeType param3){
this.param1 = param1;
...
}
}
public class HappyIndividual extends Individual{
...
}
public class SadIndividual extends Individual{
...
}
我希望能够拨打population.addIndividualsOfType(HappyIndividual)
显然,此代码不会出于多种原因(例如传递未实例化的类)。我只是想说明我想做什么的想法,这不是上述代码为什么不起作用的问题。我知道它不起作用,这就是为什么我无法弄清楚如何做这样的事情。
我整天都在忙着使用Builders和Static Factory Methods。问题是我们在这里讨论子类。子类与静态不兼容。如果我给个人一个静态工厂方法,那么我最终创建个人,而不是HappyIndividuals。 Builder也会出现类似的问题。我也希望保持这不过分复杂。
我觉得这应该很容易,但我遇到了麻烦。感谢。
答案 0 :(得分:1)
我希望能够像人口一样打电话.addIndividualsOfType(HappyIndividual)
当你要求这样做时,你非常接近。您可以改为传递HappyIndividual.class
,它是表示HappyIndividual
类的类对象。此对象本身的类型为Class
,表示运行时的类。
您的方法将如下所示:
public void addIndividualsOfType(Class<? extends Invididual> clazz) {
for (ListIterator it = indiList.listIterator(); it.hasNext(); ){
it.next();
it.add(clazz.newInstance());
}
}
对newInstance
的调用假定您的类具有不带参数的默认构造函数。否则,您需要使用getConstructor
方法获取特定的构造函数,然后使用正确的参数在该构造函数上调用newInstance
。
答案 1 :(得分:1)
基本上有两种方法可以做到这一点:
您可以继续关注当前路径并使用反射构建类:
public void addIndividualsOfType(Class<? extends Individual> clazz){
for (ListIterator it = indiList.listIterator(); it.hasNext(); ){
it.next()
it.add(clazz.newInstance()); // using no-args constructor
}
}
并使用带有参数的构造函数,用这样的代码替换it.add(clazz.newInstance())
:
Constructor<? extends Individual> cons = clazz.getConstructor(
param1.getClass(), param2.getClass(), param3.getClass());
it.add(cons.newInstance(param1, param2, param3));
(我已经省略了异常处理......但是你得到了照片。)
但是,一个更好的方法是重构代码,以便传入工厂对象而不是Class
对象。例如:
public interface IndividualFactory {
public Individual create(T1 p1, T2 p2, T3 p3);
}
public static final IndividualFactory TALL_FACTORY = new IndividualFactory() {
public Individual create(T1 p1, T2 p2, T3 p3) {
return new TallIndividual(p1, p2, p3);
}
};
public void addIndividualsOfType(IndividualFactory factory){
for (ListIterator it = indiList.listIterator(); it.hasNext(); ){
it.next()
it.add(factory.create(param1, param2, param3);
}
}
请注意,可以对基于工厂的解决方案进行静态类型检查。相比之下,反射版本必须处理许多与类型相关的运行时异常。
答案 2 :(得分:0)
传递相关课程(例如HappyPerson.class
)并通过调用Class.getConstructor(arg...)
获取构造函数,然后实例化实例。