我可以提供使用泛型类型的方法,其中泛型类型始终是类吗?

时间:2011-06-07 22:00:36

标签: java generics subclassing

我不确定我是否能够很好地传达这个问题而且我找不到更好的方法来做到这一点,因为我对java很陌生。

如果我有一个班级

,我相信最好的是举例说明
public abstract class Genome
{
    abstract public Genome randomize();
    abstract public Genome mutate();
    abstract public Genome crossOver(Genome genome);
}

我可以确保其子类始终使用泛型

来实现
public class GenomeSubclass extends Genome
{
    public GenomeSubclass randomize();
    // etc...
}

而不是合同中提供的抽象方法?

2 个答案:

答案 0 :(得分:3)

通常的方法是这样定义:

public abstract class Genome<T extends Genome<T>> {
    abstract public T randomize();
    abstract public T mutate();
    abstract public T crossOver(T genome);
}

public class GenomeSubclass extends Genome<GenomeSubclass>
{
    public GenomeSubclass randomize();
    // etc...
}

这是Comparable(或至少大部分使用Comparable)和Enum所使用的方法。

当然,这并不能避免对其他子类进行子类化。


修改以详细说明我的评论:

你不能同时拥有

class GenomeSubclass extends Genome {
    public GenomeSubclass crossOver(GenomeSubclass other);
}

class GenomeSubSubclass extends GenomeSubclass {
    public GenomeSubclass crossOver(GenomeSubSubclass other);
}

虽然两者都在实施相同的基因组方法。 GenomeSubSubclass的每个子类型都必须实现crossOver(GenomeSubclass)方法,并且不能进一步限制该参数。

当然,您可以为GenomeSubclass提供自己的类型参数:

public class GenomeSubclass<T extends GenomeSubclass<T>> extends Genome<GenomeSubclass<T>>
{
    public GenomeSubclass<T> randomize();
    // etc...
}

但是如果不以某种方式回到原始类型,你就不能直接使用这个类。 (你必须写GenomeSubclass<GenomeSubclass<GenomeSubclass<...>>>,这是不可能的。或者我在这里错误思考。)


这里的主要思想是,用作类型参数T的每个基因组子类型都将与其所有自己的子类型兼容。这意味着,我们可以拥有:

public abstract class GenomeA extends Genome<GenomeA> {}

然后

public class AImpl1 extends GenomeA {
   public GenomeA randomize();
   public GenomeA mutate();
   public GenomeA crossOver(GenomeA other);
}

public class AImpl2 extends GenomeA {
   public GenomeA randomize();
   public GenomeA mutate();
   public GenomeA crossOver(GenomeA other);
}

答案 1 :(得分:1)

不幸的是,与This对象相比,Java没有this类型。

可以通过通用技巧模拟This,但这太糟糕了。我宁愿永远不要这样做。

现在,你为什么需要它?唯一已知的用法是方法链接。如果您有不同的用例,请告诉我,这将非常有趣。

如果它仅用于方法链接,我个人认为This缺少重要性。

编辑crossover(This)是一个有趣的主题。

假设我们有超级G,以及子类AB。假设A只能crossover(A)B只能Bcrossover操作是G上的常用操作吗?

不在我们的类型系统中。当然我们可以考虑两个crossover()相关,但这种关系不能在我们的类型系统中表达。 X必须声明方法crossover(X)的要求无法强制执行。 (泛型也不能强制执行;想想X extends G<Y>

这里有必要去“extralinguistic”,使用另一种语言(英语)和另一个编译器(我们的眼球)来表达和强制执行这种关系。或者,发明一种新的静态分析仪,其具有能够表达这种关系的语法。可能需要运行时反射来执行不寻常的方法调度。

可能是这样的:

/** verbal contract: subclass X must declare method `X crossover(X)` **/
class G

    // no explicit crossover() declaration in G

    static <X extends G> X crossover(X x1, X x2)
        X1 = x1.getClass(), X2 = x2.getClass();
        check: X2 is assignable to X1
        check: X1 has method `X1 crossover(X1)`
        invoke dynamic x1.crossover(x2)

class A

    A crossover(A)