Total return
there is an immutable class:
Scope<Cmp extends Comparable<Cmp>>
public Scope<Cmp> crop(Scope<Cmp> scope) {
...
return new Scope<Cmp>(starts, ends);
}
it has many similar methods:
Timerange extends Scope<Date>
and many others (also immutable).
Id, as they are, returns an object of its type. For instance:
timerange.crop(scope)
should return a Timerange object, not a Scope.
Do I need to override each method (or use reflection)? Is there any other way to do this?
Thanks in advance Etam.
a source to share
You need some kind of factory. In this case, the factory method works fine.
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 (...);
}
}
You can add the generic base class 'this' to the base class:
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 (...);
}
}
This adds extra work to the client code.
a source to share
Java doesn't have self-type returns, so you usually need to manually override each method. See my blog on self types for a discussion of possible alternatives.
a source to share
You can try this:
class Scope<Cpm extends Comparable<Cpm>, Derived extends Scope<Cpm, Derived>> {
public Derived crop(Scope<Cmp, Derived> scope)
}
TimeRange will be defined as
class TimeRange extends Scope<Date, Timerange>
and therefore crop
will return a TimeRange object. When the output class is undefined you can use generic wildcards ( Scope<Date, ?>
)
a source to share
Do you really need Timerange
? Does he offer more than just Scope<Date>
? If not, then just use Scope<Date>
.
Another suggestion is that perhaps instead of instantiating it with the constructor, you can clone the object and then modify the fields for the new object accordingly. The reason is that the cloned object is of the same type as the original.
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;
}
a source to share