假设我有一个基类B和一个派生类D.我希望在我的基类中有一个方法foo(),它返回一个实例所属类型的新对象。所以,例如,如果我调用B.foo()它返回一个B类型的对象,而如果我调用D.foo()它返回一个D类型的对象;同时,实现仅存在于基类B中。
这可能吗?
答案 0 :(得分:3)
只要每个类都有一个默认构造函数:
public B instance() throws Exception {
return getClass().newInstance();
}
答案 1 :(得分:3)
别。使“foo”方法抽象化。
abstract class B {
public abstract B foo();
}
或通过基类构造函数接收抽象工厂:
abstract class B {
private final BFactory factory;
protected B(BFactory factory) {
this.factory = factory;
}
public B foo() {
return factory.create();
}
}
interface BFactory {
B create();
}
添加协变返回类型和泛型。
答案 2 :(得分:1)
我认为这可以使用反射,即在你的超类中:
public ClassName getFoo() throws InstantiationException, IllegalAccessException
{
return getClass().newInstance();
}
其中ClassName是基类的名称。
你必须把它投到任何你想要使用它的地方......我不确定这真的是一个很好的解决方案!
编辑: newInstance()类型方法通常是静态的,当然你不会知道你的子类的类型是什么用静态方法。
我认为没有办法让(em)静态方法(动态)创建子类的实例。
答案 3 :(得分:1)
好吧,我可能会离开,但我会假设因为“这个”总是指当前的对象,你可以做类似的事情
public B foo() {
return this.getClass().newInstance();
}
或沿着这些方向的东西?如果你创建一个D的实例然后调用d.foo()你应该得到一个D的实例作为一个B返回。你可以将它作为一个普通的对象返回,但我认为你应该在这个实例中尽可能具体。
答案 4 :(得分:1)
除了我认为如果您想要实现这一点可能存在设计缺陷,您可以尝试以下方法。
在你的问题中,你正在使用静态(类)方法,B.foo(),D.foo(),这不能使用继承来完成,因为静态方法没有动态性质,它们不参与在查找系统中。所以你没有足够的类型信息。
如果您使用的是成员函数foo(),则可以使用以下结构:
public class B {
public B foo()
throws IllegalAccessException, InstantiationException {
return this.getClass().newInstance();
}
}
public class D extends B{
}
public class Test {
public static final void main(String[] args)
{
try {
System.out.println((new B()).foo());
System.out.println((new D()).foo());
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
}
答案 5 :(得分:1)
正如其他答案所说,如果每个子类中都有无参数构造函数,则可以使用getClass()。newInstance()(确保捕获InstantiationException和IllegalAccessException)。
如果任何构造函数需要参数,您可以使用反射或(在我看来最好)定义一个像getNewInstance()这样的方法,只有在需要时才可以在子类中覆盖它。
e.g。
Thing foo() {
Thing th = getNewInstance();
// do some stuff with th
return th;
}
Thing getNewInstance() {
return getClass().newInstance();
}
然后,只有在你真正需要的情况下才能覆盖getNewInstance(),对于没有默认构造函数的子类。
Thing getNewInstance() {
return new BigThing(10, ThingSize.METRES);
}
答案 6 :(得分:0)
@Rik
嗯,真正的问题是我有一个抽象的基类Thing。而Thing有一个名为getNextThing()的方法,它返回一个新的Thing实例。
然后,我有许多子类,如BigThing,LittleThing,SomethingThing,我不想继续为每个子类重写getNextThing()方法。这似乎很浪费,因为他们都做同样的事情。
我的方法不正确吗?
答案 7 :(得分:0)
我不确定你为什么要尝试做你真正想做的事情。提供更多的上下文可能会让我们给你更多的帮助。
public class B <X extends B>{
public X foo() throws InstantiationException, IllegalAccessException{
return (X)this.getClass().newInstance();
}
}
public class C extends B<C>{
}
让我给你这条建议。倾向于教授CS课程的方式是教授们迷恋遗产,但没有想出作文。我想你可能正在寻找的是构图。因此,不要在Thing本身上调用getNextThing,也许你应该考虑制作Thing实现Iterable
这意味着你只需要编写一个Iterator来封装获取下一个东西的逻辑,因为它似乎不适合你的继承模型。这样做的另一个好处是你可以从中获得一些很好的语法设备(增强了循环理解能力)。