如何通过几个扩展级别解析泛型类型?

时间:2013-10-23 12:34:58

标签: java generics inheritance

我有以下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扩展。整个过程都根据我正在进行的具体项目进行了定制。

3 个答案:

答案 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() {}
}