Reputation: 406
If I have an interface with a generic method like the following:
public interface Thing {
void <T extends Comparable<? super T>> doSomething(List<T> objects);
}
I need that ugly generic typespec in some places, but most implementations don't actually need it:
public class ICareAboutSortingThing implements Thing {
@Override
public void <T extends Comparable<? super T>> doSomething(List<T> objects) { ... }
}
public class IDontCareAboutSortingThingx100 implements Thing {
@Override
public void <T extends Comparable<? super T>> doSomething(List<T> objects) { ... }
}
What I would want to write is something like:
public class IDontCareAboutSortingThingx100 implements Thing {
@Override
public void <?> doSomething(List<?> objects) { ... }
}
This should be fully typesafe as far as I understand, but is there any variation of this kind of shorthand that would work? I do understand that the compiler doesn't allow overriding with non-generic methods, but this is a case of replacing type arguments with wildcards. My guess is that this isn't actually supported because the compiler could just as easily support
public class IDontCareAboutSortingThingx100 implements Thing {
@Override
public void <T> doSomething(List<T> objects) { ... }
}
i.e. overriding with weaker bounds, but that doesn't seem to be allowed. Anyhow, just curious if anyone has a magic incantation for cases like this.
Upvotes: 4
Views: 1795
Reputation: 37875
Essentially what you're asking for is contravariant method parameters, e.g. a non-generic example looks like:
interface I {
void m(String s);
}
class C implements I {
@Override
public void m(Object o) {}
}
void(Object)
is a subsignature of void(String)
because the widening conversion is always OK. Java doesn't have this.
For generics, you may override a generic method to be non-generic:
class NotGeneric implements Thing {
@Override
public void doSomething(List rawList) {}
}
But you basically shouldn't do it. You will get raw type warnings and you should listen to them. It's available for backwards compatibility.
If it were me, I would just repeat the ugly generic signature because I don't think it's all that ugly.
Something else you could do would be like
interface NonGenericThing extends Thing {
@Override
default <T extends Comparable<? super T>>
void doSomething(List<T> list) {
doSomethingImpl(list);
}
void doSomethingImpl(List<?> list);
}
And then you implement NonGenericThing
instead and override doSomethingImpl
. (Prior to Java 8, NonGenericThing
must be an abstract class.)
Of course that might not be feasible if Thing
is actually a large interface. You could also declare Thing
this way to begin with, if it's appropriate.
Upvotes: 1
Reputation: 9707
You can embed the type information into a class:
public class IDontCareAboutSortingThingx100<T extends Comparable<? super T>> implements Thing<T> {
@Override
public void doSomething(List<T> objects) {
}
}
Upvotes: 0
Reputation: 65859
Not quite sure where you're trying to get to but couldn't you encapsulate the restrictions in a separate class?
public class It<T extends Comparable<? super T>> {
public List<T> them;
}
public interface Thing {
void doSomething(It<String> them);
}
Upvotes: 4