我有以下3个班级:
public class MyClass1<T extends MyClass1> {
private List list = new ArrayList();
public T add(Object... o) {
Collections.addAll(this.list, o);
return (T) this;
}
public MyClass2 two() {
MyClass2 n = new MyClass2();
add(n);
return n;
}
}
public class MyClass2<T extends MyClass2> extends MyClass1<MyClass2> {
public MyClass3 three() {
MyClass3 n = new MyClass3();
add(n);
return n;
}
}
public class MyClass3<T extends MyClass3> extends MyClass2<MyClass3> {
}
我想调用链中的方法。像这样:
MyClass1 m1 = new MyClass1();
m1.add(1).add(2).two().add(3).three().add(4);
出于某种原因,add(3)
会返回MyClass1
,我希望它返回MyClass2
。如果我从<T extends MyClass2>
移除MyClass2
,则add(3)
会根据需要返回MyClass2
,但MyClass3
无法使用类型扩展MyClass2
。
我如何才能完成这项工作,所以我可以链接所有方法,仍然使用我所有课程中的add(Object...)
方法?
更新
以上显然是一个例子。我在这里真正想要创建的是一个用于构建MySQL查询的简单工具。我有很多EJB3实体已经定义了我的表名和列名,但需要进行一些本机查询,因为有些东西是用EJB-QL无法实现的。但是,我不想在我的代码中多次指定表名和列名,因此需要一个可以使用EJB3实体创建本机MySQL查询的工具。当我使用我创建的代码时,它可能如下所示:
new Query().select().field(MyEntity_.id).field(MyEntity_.name).field(MyOtherEnt_.type);
或者:
new Query().join().left(MyOtherEnt_.myEntityId);
这里我可能有一个Query对象,它指定一些通用的MySQL语法然后扩展它。可能是这样的:查询&gt;由Select&gt;扩展由SubQuery扩展。整个过程都根据我正在进行的具体项目进行了定制。
答案 0 :(得分:2)
add(3)
返回MyClass1
,因为方法add
是类MyClass1
的成员。您必须在扩展类中重写add
方法才能返回不同的数据类型。
MyClass2
的定义应该或多或少类似
class MyClass2<T extends MyClass2> extends MyClass1<MyClass2> {
@Override
public T add(Object... o) {
super.add(o);
return (T)this;
}
public MyClass3 three() {
MyClass3 n = new MyClass3();
add(n);
return n;
}
}
无论如何,我不知道你想要实现什么,但恕我直言你采取了不好的做法。此外,在创建新的参数化对象时,您不会声明类型T
,总而言之,对于编译器和JRE,此处的所有内容都只是Object
类型。
答案 1 :(得分:2)
您最大的问题是您正在扩展原始类型。变化:
public class MyClass1<T extends MyClass1> {
到
public class MyClass1<T extends MyClass1<T>> {
使用原始类型后,将从类中删除所有通用信息。
与其他课程相似。
答案 2 :(得分:0)
现在我决定让它变得更简单,MyClass3
扩展MyClass1
而不是MyClass2
。如果我将其保持在“2级”,它就可以工作,所以如果我希望能够从{链接方法',我将只能忍受MyClass3
无法扩展MyClass2
的约束。 {1}}。我的代码看起来像这样:
MyClass1
我可以写:
public class MyClass1<T extends MyClass1> {
private List list = new ArrayList();
public T add(Object... o) {
Collections.addAll(this.list, o);
return (T) this;
}
public MyClass2 two() {
MyClass2 n = new MyClass2();
add(n);
return n;
}
}
public class MyClass2 extends MyClass1<MyClass2> {
public MyClass3 three() {
MyClass3 n = new MyClass3();
add(n);
return n;
}
}
public class MyClass3 extends MyClass1<MyClass3> {
public void four() {}
}