I have the following class.
class MyClass<T>
It uses the following constructor.
MyClass(Comparator<T> comparator, Collection<? extends T> data)
And it has a field which is set in the constructor like so:
this.data = Collections.unmodifiableCollection(data);
In the special case where T implements Comparable, I don't want to require that a comparator be passed in, since I can just use the natural ordering. So I thought I should be able to use this constructor:
public <T extends Comparable<T>> MyClass(Collection<T> data)
But there is apparently a type mismatch: cannot convert from Collection<T> to Collection<? extends T>
in the assignment statement above. I've tried all sorts of things: adding more generic parameters, and so on, but none work. I seem unable to specify a bound that says: if you have a type T that implements Comparable, do the straightforward thing.
Any ideas?
Thanks.
Unfortunately I don't think this kind of "if Comparable do this else do that" logic is possible with the Java type system.
You could split the Comparable and non-Comparable cases into separate classes and hide them behind an interface, something like this:
interface Interface<T> {
public void processData();
}
class MyClass<T> implements Interface<T> {
private final Collection<? extends T> data;
MyClass(Comparator<T> comparator, Collection<? extends T> data) {
this.data = data;
}
public void processData() {
// ...
}
}
class MyCompClass<T extends Comparable<T>> implements Interface<T> {
private final Collection<? extends T> data;
MyCompClass(Collection<? extends T> data) {
this.data = data;
}
public void processData() {
// ...
}
}
class Factory {
static <T extends Comparable<T>> Interface<T> create(Collection<? extends T> data) {
return new MyCompClass<T>(data);
}
static <T> Interface<T> create(Comparator<T> comparator, Collection<? extends T> data) {
return new MyClass<T>(comparator, data);
}
}
But this might result in a lot of duplicated code. Another option is to leave MyClass requiring a Comparator in its constructor, and build that comparator in the factory:
class MyClass<T> {
private final Collection<? extends T> data;
MyClass(Comparator<T> comparator, Collection<? extends T> data) {
this.data = data;
}
public void processData() {
// ...
}
}
class Factory {
static <T extends Comparable<T>> MyClass<T> create(Collection<? extends T> data) {
return new MyClass<T>(new Comparator<T>() {
public int compare(T o1, T o2) {
return o1.compareTo(o2);
}
}, data);
}
static <T> MyClass<T> create(Comparator<T> comparator, Collection<? extends T> data) {
return new MyClass<T>(comparator, data);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With