I'm upgrading some code to Java 5 and am clearly not understanding something with Generics. I have other classes which implement Comparable once, which I've been able to implement. But now I've got a class which, due to inheritance, ends up trying to implement Comparable for 2 types. Here's my situation:
I've got the following classes/interfaces:
interface Foo extends Comparable<Foo>
interface Bar extends Comparable<Bar>
abstract class BarDescription implements Bar
class FooBar extends BarDescription implements Foo
With this, I get the error 'interface Comparable cannot be implemented more than once with different arguments...'
Why can't I have a compareTo(Foo foo) implemented in FooBar, and also a compareTo(Bar) implemented in BarDescription? Isn't this simply method overloading?
Edit: I have many classes which extend BarDescription. If I remove the type parameter for Comparable on Bar, leaving it in the raw state, then I get a bunch of compiler warnings when sorting all the classes which extend BarDescription. Would this be solved with the wildcards answer below? That answer looks quite complicated and difficult to understand for maintenance.
Generics don't exist after bytecode has been compiled.
Restrictions from this: You can't implement / extend two or more interfaces / classes that would be same without the generic parameter and are different with the generic parameter.
What you could do if you really really want type safety is:
interface Foo<T extends Foo<?>> extends Comparable<T>
interface Bar<T extends Bar<?>> extends Comparable<T>
abstract class BarDescription<T extends Bar<?>> implements Bar<T>
class FooBar extends BarDescription<FooBar> implements Foo<FooBar>
I'd write a couple of Comparators and be done with it.
Having multiple implementations of generic interfaces would run into problems when you consider wildcards.
This does not depend upon erasure.
Related
I know in Java Generics, there is T extends something, but I want T implements something.
Is there any way to achieve this other than using the explicit cast?
For instance, I want to make sure everything passed to sorting algorithm implements Comparable. Implements, not extends.
Thank you.
For generic type bounds, extends isn't limited to classes; you can also use it for interfaces. For example, <T extends Runnable> is OK.
My case is different but as an example
public interface Comparable<T>
would allow me to say:
public class MyType implements Comparable<OtherType>
but this is rarely what you want to achieve.
Is there a way to force me to say:
public class MyType implements Comparable<MyType>
The closest I got is:
public interface Comparable<T extends Comparable<T>>
This only works partially, as it won't allow OtherType if it's not comparable itself, but would allow:
public class MyType implements Comparable<Integer>
as it meets the conditions.
This is not possible in Java.
Consider if it were possible to require that the type argument of Comparable be the same as the implementing class. Then if you had a class Foo implements Comparable<Foo>, and then also a class Bar extends Foo, Bar would also automatically implement Comparable<Foo> by the way that inheritance in Java works. But that would violate the constraint that the implementing class is the same as the type argument, as Bar does not implement Comparable<Bar> (and you can't even explicitly have Bar implement Comparable<Bar>, as a class cannot implement a generic type with two different type arguments).
When I extend a class, say class A in class B, i'm implementing all interfaces that class A implements.
In the following,
interface INTF { ... }
class A implements INTF { ... }
class B extends A { .... }
class B, being a descendant of class A, is implementing INTF.
So, what's my gain in declaring class B as
class B extends A implements INTF { .... }
?
//===========================
EDIT:
Java APIs are doing this. Eg.:
public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V> { ...
what for ?
TIA
There is no difference if your sub class restates that it implements an interface.But there is a huge gain when it comes to Reflection API.I have personally faced it..
When you call B.class.getInterfaces() ,it returns a Class[] containing only those interfaces explicitly declared by the class and not its superclasses,although in reality it is implementing interfaces which are implemented by its superclasses.
To solve it,you need to recursively call the super class and get all the interfaces implemented.Declaring an interface explicitly in your sub class will help you in this case
You don't have to re-declare the interface again. However, there will be differences if you using Java reflections - B.class.getInterfaces().
If you don't re-declare the interface again. B.class.getInterfaces() -- return zero interface
If you re-declare the interface B.class.getInterfaces() - Return one interface
So deciding to re-declare the interface again or Not depending on how you use java reflections on it. For most case, we don't re-declare it again.
You don't have to specify the interface again. You could specify all the implemented methods again, but you don't have to do that either.
If A changes the interface it implements in future B might not need to know about it.
It makes no difference whether you specify that B implements INTF or not, since it must implement it anyway, since A is implementing it.
I'm not sure why Java APIs are doing it. I'm assuming they simply want to make it more clear to the user of LinkedHashMap that it implements Map (otherwise the user would have to look at the declaration of HashMap to find this out).
This question is a follow up from Java Generics Wildcarding With Multiple Classes.
I'm writing an interface like this:
public interface SomeInterface {
public Class<? extends SomeClass implements OtherInterface> getClassForObject(Object object);
}
I know that this is wrong syntax, as is Class<? extends SomeClass & OtherInterface>, and it seems all options.
I can't have the interface do what was suggested in the answer to the question linked above (public interface SomeInterface<T extends SomeClass & OtherInterface>) because implementations of this interface might want to return different things for different inputs.
I also can't create an abstract class that extends SomeClass and implements OtherInterface and have everything extend from that because there are many existing implementations of SomeClass that clients may want to extend from.
Is there any way to force implementations of this interface to return a type that fits both constraints? Besides throwing a runtime exception somewhere else in the code?
You cannot impose multiple restrictions on a wildcard. You can declare a generic type parameter on the method instead of the interface itself, and you can impose multiple restrictions on it. Try:
public interface SomeInterface {
public <T extends SomeClass & OtherInterface> Class<T>
getClassForObject(Object object);
}
I need to parameterise my class by Enum with some concrete methods, something like:
class K<E extends Enum<E> implements SomeInterface>
But Eclipse prohibit me to use "implements" word in "<>". What can I do to solve my problem? Is there any sensible reason why can't I use "implements" in definition of generic type?
Generic constraints use the word extends for both base classes and interfaces.
To constrain on multiple types, use an &:
class K<E extends Enum<E> & SomeInterface>
You would use extends in this case:
class K<E extends Enum<E>&SomeInterface>
Please note that if it needs to also extend a class it must come before any interfaces.