通用回报

时间:2009-05-11 16:37:50

标签: java generics polymorphism return

有一个不可变的类:

Scope<Cmp extends Comparable<Cmp>>
public Scope<Cmp> crop(Scope<Cmp> scope) {
    ...
    return new Scope<Cmp>(starts, ends);
}

许多类似的方法扩展为:

Timerange extends Scope<Date>

很多其他人(也是不可变的)。

我喜欢他们返回其类型的对象。例如:

timerange.crop(scope)

应该返回Timerange对象,而不是Scope。

我是否必须覆盖每个方法(或使用反射)? 还有另一种方法吗?

提前致谢, 艾格。

4 个答案:

答案 0 :(得分:4)

你需要某种工厂。在这种情况下,工厂方法可以正常工作。

public abstract class Scope<E extends Comparable<E>> {
    abstract Scope<E> create(E start, E end);

    public Scope<E> crop(Scope<E> scope) {
        ...
        return create(starts, ends);
    }
}
public TimeRange extends Scope<Date> {
    Scope<Date> create(Date start, Date end) {
        return new TimeRange (...);
    }
}

您可能希望将基本的'this'参数添加到基类:

public abstract class Scope<THIS extends Scope<THIS, E>, E extend Comparable<E>> {
    abstract THIS create(E start, E end);

    public THIS crop(Scope<E> scope) {
        ...
        return create(starts, ends);
    }
}
public TimeRange extends Scope<TimeRange,Date> {
    TimeRange create(Date start, Date end) {
        return new TimeRange (...);
    }
}

这确实为客户端代码添加了额外的工作。

答案 1 :(得分:2)

Java没有自我类型返回,因此您通常需要手动覆盖每个方法。有关可能的替代方案的讨论,请参见my blog on "self types"

答案 2 :(得分:2)

您可以尝试以下方法:

class Scope<Cpm extends Comparable<Cpm>, Derived extends Scope<Cpm, Derived>> {
  public Derived crop(Scope<Cmp, Derived> scope)
}

TimeRange将被定义为

class TimeRange extends Scope<Date, Timerange>

所以crop会返回一个TimeRange对象。如果未定义派生类,则可以使用通用通配符(Scope<Date, ?>

答案 3 :(得分:0)

你真的需要Timerange吗?它提供的不仅仅是Scope<Date>吗?如果没有,那么只需使用Scope<Date>

另一个建议是,可能不是使用构造函数实例化它,而是可以克隆该对象,然后为新对象适当地修改字段。原因是克隆的对象与原始对象的类型相同。

Scope<Cmp extends Comparable<Cmp>> implements Cloneable
public Scope<Cmp> crop(Scope<Cmp> scope) {
    ...
    Scope<Cmp> result = (Scope<Cmp>)super.clone();
    result.init(starts, ends); // sets the fields for a cloned object
                               // init() could be private
    return result;
}