我有一个abstract
class
,它有一个abstract
方法。我希望这个方法return
与覆盖方法的类相同的数据类型,而不必转换create
的结果或必须在上面创建新的方法声明每个子类。我希望所有这些都可以从父类中无声地声明。
我希望该方法返回一个对象,其数据类型与调用它的类相同。
编辑:我删除了印刷品,因为人们对我的要求感到困惑abstract class A
{
public abstract ... create();
}
class B extends A
{
@override
public ... create()
{
return new B...;
}
}
class C extends A
{
@override
public ... create()
{
return new C...;
}
}
这样
B x1 = new B();
B x2 = x1.create();
// Since create was called on a B object
// a B object is returned, NOT AN "A" object
C y1 = new C();
C y2 = y1.create();
// create makes a C object this time,
// because it's called on a C object
// Problem: create() returns A object, even when
// called from class B or C.
// I want create() to return a B object if called from a B object.
这会是一个好方法吗?感谢。
答案 0 :(得分:5)
我不再认为这是正确的答案。它是一个答案,但过于复杂。请参阅my other answer。
没有" self"输入Java的泛型。你能做的最好就是使用自我约束的泛型:
abstract class A<T extends A<T>>
{
public abstract T create();
}
然后,在您的子类中:
class B extends A<B>
{
@override
public B create()
{
return new B...;
}
}
答案 1 :(得分:1)
实际上,有一种比使用my other answer更简单的方法:只需在子类中使用协变返回类型:
abstract class A {
public abstract A create();
}
class B extends A {
@Override public B create() {
return new B...
}
}
如果你正在处理A
的实例,这会更令人愉快,因为你不必使它成为通用的(或者是颤抖的,原始的)。
它也提供了返回“自我”类型的保证,即根本不保证。
答案 2 :(得分:0)
我必须质疑设计方法。
我要去
abstract class A {
abstract Supplier<? extends A> create();
}
与
class B extends A {
public Supplier<B> create() {
return B::new;
}
}
(和C相应)。 然后,有
A b = new B();
A anotherB = b.create().get(); // will create a B
A c = new C();
A anotherC = c.create().get(); // will create a C
答案 3 :(得分:0)
您不需要将create
方法摘要化。如果所有子类都有一个无参构造函数,那么你可以写一下(在类A
中)
public A create() {
try {
return getClass().newInstance();
} catch (InstantiationException | IllegalAccessException e) {
return null;
}
}
这将检查您调用方法的对象的类;并使用其无参数构造函数创建同一类的新对象。
<强>更新强>
OP的评论表明他们不想投出返回的值。如果这是一项要求,则可以通过更改方法签名来避免转换,如下所示。public <T extends A> T create() {
try {
return getClass().newInstance();
} catch (InstantiationException | IllegalAccessException e) {
return null;
}
}
答案 4 :(得分:0)
this.getClass()
获取类对象,或this.getClass().getSimpleName()
获取类名的字符串。