1

我有以下 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 语法,然后扩展它。它可能是这样的:查询 > 由 Select 扩展 > 由 SubQuery 扩展。整个事情都是针对我正在从事的特定项目定制的。

4

3 回答 3

2

您最大的问题是您正在扩展原始类型。改变:

public class MyClass1<T extends MyClass1> {

public class MyClass1<T extends MyClass1<T>> {

一旦你使用了原始类型,所有的泛型信息都会从类中删除。

其他类也类似。

于 2013-10-23T13:12:20.137 回答
2

add(3)返回MyClass1,因为 methodadd是 class 的成员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类型。

于 2013-10-23T12:48:02.527 回答
0

现在我决定让它更简单一点,并使用MyClass3扩展MyClass1而不是MyClass2. MyClass3如果我将它保持在“2 级”,它就可以工作,所以MyClass2如果我想能够从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() {}
}

我可以写:

MyClass1 m1 = new MyClass1();
m1.add(1).add(2).two().add(3).add(4).three().add(5).add(6).four();
于 2013-10-24T07:46:01.313 回答